From 8d5403aa4a341150d4bd877e65ed98b6051565b3 Mon Sep 17 00:00:00 2001 From: Dmitry Selyutin Date: Thu, 19 Jan 2023 07:25:01 +0300 Subject: [PATCH] pysvp64asm: drop obsolete code --- src/openpower/sv/trans/svp64.py | 851 +------------------------------- 1 file changed, 6 insertions(+), 845 deletions(-) diff --git a/src/openpower/sv/trans/svp64.py b/src/openpower/sv/trans/svp64.py index 7792a9a3..3a4cdeb1 100644 --- a/src/openpower/sv/trans/svp64.py +++ b/src/openpower/sv/trans/svp64.py @@ -38,194 +38,11 @@ from openpower.decoder.power_enums import find_wiki_dir from openpower.util import log -# decode GPR into sv extra -def get_extra_gpr(etype, regmode, field): - if regmode == 'scalar': - # cut into 2-bits 5-bits SS FFFFF - sv_extra = field >> 5 - field = field & 0b11111 - else: - # cut into 5-bits 2-bits FFFFF SS - sv_extra = field & 0b11 - field = field >> 2 - return sv_extra, field - - -# decode 3-bit CR into sv extra -def get_extra_cr_3bit(etype, regmode, field): - if regmode == 'scalar': - # cut into 2-bits 3-bits SS FFF - sv_extra = field >> 3 - field = field & 0b111 - else: - # cut into 3-bits 4-bits FFF SSSS but will cut 2 zeros off later - sv_extra = field & 0b1111 - field = field >> 4 - return sv_extra, field - - -# decodes SUBVL -def decode_subvl(encoding): - pmap = {'2': 0b01, '3': 0b10, '4': 0b11} - assert encoding in pmap, \ - "encoding %s for SUBVL not recognised" % encoding - return pmap[encoding] - - -# decodes elwidth -def decode_elwidth(encoding): - pmap = {'8': 0b11, '16': 0b10, '32': 0b01} - assert encoding in pmap, \ - "encoding %s for elwidth not recognised" % encoding - return pmap[encoding] - - -# decodes predicate register encoding -def decode_predicate(encoding): - pmap = { # integer - '1<> 1 # CR - return int(si) - - -# partial-decode fail-first mode -def decode_ffirst(encoding): - if encoding in ['RC1', '~RC1']: - return encoding - return decode_bo(encoding) - - -def decode_reg(field, macros=None): - if macros is None: - macros = {} - # decode the field number. "5.v" or "3.s" or "9" - # and now also "*0", and "*%0". note: *NOT* to add "*%rNNN" etc. - # https://bugs.libre-soc.org/show_bug.cgi?id=884#c0 - if field.startswith(("*%", "*")): - if field.startswith("*%"): - field = field[2:] - else: - field = field[1:] - while field in macros: - field = macros[field] - return int(field), "vector" # actual register number - - # try old convention (to be retired) - field = field.split(".") - regmode = 'scalar' # default - if len(field) == 2: - if field[1] == 's': - regmode = 'scalar' - elif field[1] == 'v': - regmode = 'vector' - field = int(field[0]) # actual register number - return field, regmode - - -def decode_imm(field): - ldst_imm = "(" in field and field[-1] == ')' - if ldst_imm: - return field[:-1].split("(") - else: - return None, field - - -def crf_extra(etype, rname, extra_idx, regmode, field, extras): - """takes a CR Field number (CR0-CR127), splits into EXTRA2/3 and v3.0 - the scalar/vector mode (crNN.v or crNN.s) changes both the format - of the EXTRA2/3 encoding as well as what range of registers is possible. - this function can be used for both BF/BFA and BA/BB/BT by first removing - the bottom 2 bits of BA/BB/BT then re-instating them after encoding. - see https://libre-soc.org/openpower/sv/svp64/appendix/#cr_extra - for specification - """ - sv_extra, field = get_extra_cr_3bit(etype, regmode, field) - # now sanity-check (and shrink afterwards) - if etype == 'EXTRA2': - # 3-bit CR Field (BF, BFA) EXTRA2 encoding - if regmode == 'scalar': - # range is CR0-CR15 in increments of 1 - assert (sv_extra >> 1) == 0, \ - "scalar CR %s cannot fit into EXTRA2 %s" % \ - (rname, str(extras[extra_idx])) - # all good: encode as scalar - sv_extra = sv_extra & 0b01 - else: # vector - # range is CR0-CR127 in increments of 16 - assert sv_extra & 0b111 == 0, \ - "vector CR %s cannot fit into EXTRA2 %s" % \ - (rname, str(extras[extra_idx])) - # all good: encode as vector (bit 2 set) - sv_extra = 0b10 | (sv_extra >> 3) - else: - # 3-bit CR Field (BF, BFA) EXTRA3 encoding - if regmode == 'scalar': - # range is CR0-CR31 in increments of 1 - assert (sv_extra >> 2) == 0, \ - "scalar CR %s cannot fit into EXTRA3 %s" % \ - (rname, str(extras[extra_idx])) - # all good: encode as scalar - sv_extra = sv_extra & 0b11 - else: # vector - # range is CR0-CR127 in increments of 8 - assert sv_extra & 0b11 == 0, \ - "vector CR %s cannot fit into EXTRA3 %s" % \ - (rname, str(extras[extra_idx])) - # all good: encode as vector (bit 3 set) - sv_extra = 0b100 | (sv_extra >> 2) - return sv_extra, field - +DB = Database(find_wiki_dir()) -def to_number(field): - if field.startswith("0x"): - return eval(field) - if field.startswith("0b"): - return eval(field) - return int(field) - -DB = Database(find_wiki_dir()) +class AssemblerError(ValueError): + pass # decodes svp64 assembly listings and creates EXT001 svp64 prefixes @@ -268,8 +85,7 @@ class SVP64Asm: # identify if it is a word instruction record = None - if os.environ.get("INSNDB"): - record = DB[opcode] + record = DB[opcode] if record is not None: insn = WordInstruction.assemble(db=DB, entry=opcode, arguments=fields) @@ -293,8 +109,7 @@ class SVP64Asm: v30b_op = v30b_op_orig record = None - if os.environ.get("INSNDB"): - record = DB[v30b_op] + record = DB[v30b_op] if record is not None: insn = SVP64Instruction.assemble(db=DB, entry=v30b_op_orig, @@ -303,661 +118,7 @@ class SVP64Asm: yield from insn.disassemble(db=DB, style=Style.LEGACY) return - # look up the 32-bit op (original, with "." if it has it) - if v30b_op_orig in isa.instr: - isa_instr = isa.instr[v30b_op_orig] - else: - raise Exception("opcode %s of '%s' not supported" % - (v30b_op_orig, insn)) - - # look up the svp64 op, first the original (with "." if it has it) - if v30b_op_orig in svp64.instrs: - rm = svp64.instrs[v30b_op_orig] # one row of the svp64 RM CSV - # then without the "." (if there was one) - elif v30b_op in svp64.instrs: - rm = svp64.instrs[v30b_op] # one row of the svp64 RM CSV - else: - raise Exception(f"opcode {v30b_op_orig!r} of " - f"{insn!r} not an svp64 instruction") - - # get regs info e.g. "RT,RA,RB" - v30b_regs = isa_instr.regs[0] - log("v3.0B op", v30b_op, "Rc=1" if rc_mode else '') - log("v3.0B regs", opcode, v30b_regs) - log("RM", rm) - - # right. the first thing to do is identify the ordering of - # the registers, by name. the EXTRA2/3 ordering is in - # rm['0']..rm['3'] but those fields contain the names RA, BB - # etc. we have to read the pseudocode to understand which - # reg is which in our instruction. sigh. - - # first turn the svp64 rm into a "by name" dict, recording - # which position in the RM EXTRA it goes into - # also: record if the src or dest was a CR, for sanity-checking - # (elwidth overrides on CRs are banned) - decode = decode_extra(rm) - dest_reg_cr, src_reg_cr, svp64_src, svp64_dest = decode - - log("EXTRA field index, src", svp64_src) - log("EXTRA field index, dest", svp64_dest) - - # okaaay now we identify the field value (opcode N,N,N) with - # the pseudo-code info (opcode RT, RA, RB) - assert len(fields) == len(v30b_regs), \ - "length of fields %s must match insn `%s` fields %s" % \ - (str(v30b_regs), insn, str(fields)) - opregfields = zip(fields, v30b_regs) # err that was easy - - # now for each of those find its place in the EXTRA encoding - # note there is the possibility (for LD/ST-with-update) of - # RA occurring **TWICE**. to avoid it getting added to the - # v3.0B suffix twice, we spot it as a duplicate, here - extras = OrderedDict() - for idx, (field, regname) in enumerate(opregfields): - imm, regname = decode_imm(regname) - rtype = get_regtype(regname) - log(" idx find", rtype, idx, field, regname, imm) - if rtype is None: - # probably an immediate field, append it straight - extras[('imm', idx, False)] = (idx, field, None, None, None) - continue - extra = svp64_src.get(regname, None) - if extra is not None: - extra = ('s', extra, False) # not a duplicate - extras[extra] = (idx, field, regname, rtype, imm) - log(" idx src", idx, extra, extras[extra]) - dextra = svp64_dest.get(regname, None) - log("regname in", regname, dextra) - if dextra is not None: - is_a_duplicate = extra is not None # duplicate spotted - dextra = ('d', dextra, is_a_duplicate) - extras[dextra] = (idx, field, regname, rtype, imm) - log(" idx dst", idx, extra, extras[dextra]) - - # great! got the extra fields in their associated positions: - # also we know the register type. now to create the EXTRA encodings - etype = rm['Etype'] # Extra type: EXTRA3/EXTRA2 - ptype = rm['Ptype'] # Predication type: Twin / Single - extra_bits = 0 - v30b_newfields = [] - for extra_idx, (idx, field, rname, rtype, iname) in extras.items(): - # is it a field we don't alter/examine? if so just put it - # into newfields - if rtype is None: - v30b_newfields.append(field) - continue - - # identify if this is a ld/st immediate(reg) thing - ldst_imm = "(" in field and field[-1] == ')' - if ldst_imm: - immed, field = field[:-1].split("(") - - field, regmode = decode_reg(field, macros=macros) - log(" ", extra_idx, rname, rtype, - regmode, iname, field, end=" ") - - # see Mode field https://libre-soc.org/openpower/sv/svp64/ - # XXX TODO: the following is a bit of a laborious repeated - # mess, which could (and should) easily be parameterised. - # XXX also TODO: the LD/ST modes which are different - # https://libre-soc.org/openpower/sv/ldst/ - - # rright. SVP64 register numbering is from 0 to 127 - # for GPRs, FPRs *and* CR Fields, where for v3.0 the GPRs and RPFs - # are 0-31 and CR Fields are only 0-7. the SVP64 RM "Extra" - # area is used to extend the numbering from the 32-bit - # instruction, and also to record whether the register - # is scalar or vector. on a per-operand basis. this - # results in a slightly finnicky encoding: here we go... - - # encode SV-GPR and SV-FPR field into extra, v3.0field - if rtype in ['GPR', 'FPR']: - sv_extra, field = get_extra_gpr(etype, regmode, field) - # now sanity-check. EXTRA3 is ok, EXTRA2 has limits - # (and shrink to a single bit if ok) - if etype == 'EXTRA2': - if regmode == 'scalar': - # range is r0-r63 in increments of 1 - assert (sv_extra >> 1) == 0, \ - "scalar GPR %s cannot fit into EXTRA2 %s" % \ - (rname, str(extras[extra_idx])) - # all good: encode as scalar - sv_extra = sv_extra & 0b01 - else: - # range is r0-r127 in increments of 2 (r0 r2 ... r126) - assert sv_extra & 0b01 == 0, \ - "%s: vector field %s cannot fit " \ - "into EXTRA2 %s" % \ - (insn, rname, str(extras[extra_idx])) - # all good: encode as vector (bit 2 set) - sv_extra = 0b10 | (sv_extra >> 1) - elif regmode == 'vector': - # EXTRA3 vector bit needs marking - sv_extra |= 0b100 - - # encode SV-CR 3-bit field into extra, v3.0field. - # 3-bit is for things like BF and BFA - elif rtype == 'CR_3bit': - sv_extra, field = crf_extra(etype, rname, extra_idx, - regmode, field, extras) - - # encode SV-CR 5-bit field into extra, v3.0field - # 5-bit is for things like BA BB BC BT etc. - # *sigh* this is the same as 3-bit except the 2 LSBs of the - # 5-bit field are passed through unaltered. - elif rtype == 'CR_5bit': - cr_subfield = field & 0b11 # record bottom 2 bits for later - field = field >> 2 # strip bottom 2 bits - # use the exact same 3-bit function for the top 3 bits - sv_extra, field = crf_extra(etype, rname, extra_idx, - regmode, field, extras) - # reconstruct the actual 5-bit CR field (preserving the - # bottom 2 bits, unaltered) - field = (field << 2) | cr_subfield - - else: - raise Exception("no type match: %s" % rtype) - - # capture the extra field info - log("=>", "%5s" % bin(sv_extra), field) - extras[extra_idx] = sv_extra - - # append altered field value to v3.0b, differs for LDST - # note that duplicates are skipped e.g. EXTRA2 contains - # *BOTH* s:RA *AND* d:RA which happens on LD/ST-with-update - srcdest, idx, duplicate = extra_idx - if duplicate: # skip adding to v3.0b fields, already added - continue - if ldst_imm: - v30b_newfields.append(("%s(%s)" % (immed, str(field)))) - else: - v30b_newfields.append(str(field)) - - log("new v3.0B fields", v30b_op, v30b_newfields) - log("extras", extras) - - # rright. now we have all the info. start creating SVP64 instruction. - svp64_insn = SVP64Instruction.pair(prefix=0, suffix=0) - svp64_prefix = svp64_insn.prefix - svp64_rm = svp64_insn.prefix.rm - - # begin with EXTRA fields - for idx, sv_extra in extras.items(): - log(idx) - if idx is None: - continue - if idx[0] == 'imm': - continue - srcdest, idx, duplicate = idx - if etype == 'EXTRA2': - svp64_rm.extra2[idx] = sv_extra - else: - svp64_rm.extra3[idx] = sv_extra - - # identify if the op is a LD/ST. - # see https://libre-soc.org/openpower/sv/ldst/ - is_ldst = rm['mode'] in ['LDST_IDX', 'LDST_IMM'] - is_ldst_idx = rm['mode'] == 'LDST_IDX' - is_ldst_imm = rm['mode'] == 'LDST_IMM' - is_ld = v30b_op.startswith("l") and is_ldst - is_st = v30b_op.startswith("s") and is_ldst - - # branch-conditional or CR detection - is_bc = rm['mode'] == 'BRANCH' - is_cr = rm['mode'] == 'CROP' - - # parts of svp64_rm - mmode = 0 # bit 0 - pmask = 0 # bits 1-3 - destwid = 0 # bits 4-5 - srcwid = 0 # bits 6-7 - subvl = 0 # bits 8-9 - smask = 0 # bits 16-18 but only for twin-predication - mode = 0 # bits 19-23 - - mask_m_specified = False - has_pmask = False - has_smask = False - - saturation = None - src_zero = 0 - dst_zero = 0 - sv_mode = None - - mapreduce = False - reverse_gear = False - mapreduce_crm = False - - predresult = False - failfirst = False - ldst_elstride = 0 - ldst_postinc = 0 - sea = False - - vli = False - sea = False - - # ok let's start identifying opcode augmentation fields - for encmode in opmodes: - # predicate mask (src and dest) - if encmode.startswith("m="): - pme = encmode - pmmode, pmask = decode_predicate(encmode[2:]) - smmode, smask = pmmode, pmask - mmode = pmmode - mask_m_specified = True - # predicate mask (dest) - elif encmode.startswith("dm="): - pme = encmode - pmmode, pmask = decode_predicate(encmode[3:]) - mmode = pmmode - has_pmask = True - # predicate mask (src, twin-pred) - elif encmode.startswith("sm="): - sme = encmode - smmode, smask = decode_predicate(encmode[3:]) - mmode = smmode - has_smask = True - # vec2/3/4 - elif encmode.startswith("vec"): - subvl = decode_subvl(encmode[3:]) - # elwidth (both src and dest, like mask) - elif encmode.startswith("w="): - destwid = decode_elwidth(encmode[2:]) - srcwid = decode_elwidth(encmode[2:]) - # just dest width - elif encmode.startswith("dw="): - destwid = decode_elwidth(encmode[3:]) - # just src width - elif encmode.startswith("sw="): - srcwid = decode_elwidth(encmode[3:]) - # post-increment - elif encmode == 'pi': - ldst_postinc = 1 - # in indexed mode, set sv_mode=0b00 - assert is_ldst_imm is True - sv_mode = 0b00 - # element-strided LD/ST - elif encmode == 'els': - ldst_elstride = 1 - # in indexed mode, set sv_mode=0b01 - if is_ldst_idx: - sv_mode = 0b01 - # saturation - elif encmode == 'sats': - assert sv_mode is None - saturation = 1 - sv_mode = 0b10 - elif encmode == 'satu': - assert sv_mode is None - sv_mode = 0b10 - saturation = 0 - # predicate zeroing - elif encmode == 'zz': # TODO, a lot more checking on legality - dst_zero = 1 # NOT on cr_ops, that's RM[6] - src_zero = 1 - elif encmode == 'sz': - src_zero = 1 - elif encmode == 'dz': - dst_zero = 1 - # failfirst - elif encmode.startswith("ff="): - assert sv_mode is None - if is_cr: # sigh, CROPs is different - sv_mode = 0b10 - else: - sv_mode = 0b01 - failfirst = decode_ffirst(encmode[3:]) - assert sea is False, "cannot use failfirst with signed-address" - # predicate-result, interestingly same as fail-first - elif encmode.startswith("pr="): - assert sv_mode is None - sv_mode = 0b11 - predresult = decode_ffirst(encmode[3:]) - # map-reduce mode, reverse-gear - elif encmode == 'mrr': - assert sv_mode is None - sv_mode = 0b00 - mapreduce = True - reverse_gear = True - # map-reduce mode - elif encmode == 'mr': - assert sv_mode is None - sv_mode = 0b00 - mapreduce = True - elif encmode == 'crm': # CR on map-reduce - assert sv_mode is None - sv_mode = 0b00 - mapreduce_crm = True - elif encmode == 'vli': - assert failfirst is not False, "VLi only allowed in failfirst" - vli = True - elif encmode == 'sea': - assert is_ldst_idx - sea = True - assert failfirst is False, "cannot use ffirst+signed-address" - elif is_bc: - if encmode == 'all': - svp64_rm.branch.ALL = 1 - elif encmode == 'snz': - svp64_rm.branch.sz = 1 - svp64_rm.branch.SNZ = 1 - elif encmode == 'sl': - svp64_rm.branch.SL = 1 - elif encmode == 'slu': - svp64_rm.branch.SLu = 1 - elif encmode == 'lru': - svp64_rm.branch.LRu = 1 - elif encmode == 'vs': - svp64_rm.branch.VLS = 1 - elif encmode == 'vsi': - svp64_rm.branch.VLS = 1 - svp64_rm.branch.vls.VLi = 1 - elif encmode == 'vsb': - svp64_rm.branch.VLS = 1 - svp64_rm.branch.vls.VSb = 1 - elif encmode == 'vsbi': - svp64_rm.branch.VLS = 1 - svp64_rm.branch.vls.VSb = 1 - svp64_rm.branch.vls.VLi = 1 - elif encmode == 'ctr': - svp64_rm.branch.CTR = 1 - elif encmode == 'cti': - svp64_rm.branch.CTR = 1 - svp64_rm.branch.ctr.CTi = 1 - else: - raise AssertionError("unknown encmode %s" % encmode) - else: - raise AssertionError("unknown encmode %s" % encmode) - - # post-inc only available on ld-with-update - if ldst_postinc: - assert "u" in opcode, "/pi only available on ld/st-update" - - # sanity check if dz/zz used in branch-mode - if is_bc and dst_zero: - raise AssertionError("dz/zz not supported in branch, use 'sz'") - - # check sea *after* all qualifiers are evaluated - if sea: - assert sv_mode in (None, 0b00, 0b01) - - if ptype == '2P': - # since m=xx takes precedence (overrides) sm=xx and dm=xx, - # treat them as mutually exclusive - if mask_m_specified: - assert not has_smask,\ - "cannot have both source-mask and predicate mask" - assert not has_pmask,\ - "cannot have both dest-mask and predicate mask" - # since the default is INT predication (ALWAYS), if you - # specify one CR mask, you must specify both, to avoid - # mixing INT and CR reg types - if has_pmask and pmmode == 1: - assert has_smask, \ - "need explicit source-mask in CR twin predication" - if has_smask and smmode == 1: - assert has_pmask, \ - "need explicit dest-mask in CR twin predication" - # sanity-check that 2Pred mask is same mode - if has_pmask and has_smask: - assert smmode == pmmode, \ - "predicate masks %s and %s must be same reg type" % \ - (pme, sme) - - # sanity-check that twin-predication mask only specified in 2P mode - if ptype == '1P': - assert not has_smask, \ - "source-mask can only be specified on Twin-predicate ops" - assert not has_pmask, \ - "dest-mask can only be specified on Twin-predicate ops" - - # construct the mode field, doing sanity-checking along the way - if src_zero: - assert has_smask or mask_m_specified, \ - "src zeroing requires a source predicate" - if dst_zero: - assert has_pmask or mask_m_specified, \ - "dest zeroing requires a dest predicate" - - # okaaay, so there are 4 different modes, here, which will be - # partly-merged-in: is_ldst is merged in with "normal", but - # is_bc is so different it's done separately. likewise is_cr - # (when it is done). here are the maps: - - # for "normal" arithmetic: https://libre-soc.org/openpower/sv/normal/ - """ - | 0-1 | 2 | 3 4 | description | - | --- | --- |---------|-------------------------- | - | 00 | 0 | dz sz | simple mode | - | 00 | 1 | 0 RG | scalar reduce mode (mapreduce) | - | 01 | inv | CR-bit | Rc=1: ffirst CR sel | - | 01 | inv | VLi RC1 | Rc=0: ffirst z/nonz | - | 10 | N | dz sz | sat mode: N=0/1 u/s | - | 11 | inv | CR-bit | Rc=1: pred-result CR sel | - | 11 | inv | zz RC1 | Rc=0: pred-result z/nonz | - """ - - # https://libre-soc.org/openpower/sv/ldst/ - # for LD/ST-immediate: - """ - | 0-1 | 2 | 3 4 | description | - | --- | --- |---------|--------------------------- | - | 00 | 0 | zz els | normal mode | - | 00 | 1 | pi lf | post-inc, LD-fault-first | - | 01 | inv | CR-bit | Rc=1: ffirst CR sel | - | 01 | inv | els RC1 | Rc=0: ffirst z/nonz | - | 10 | N | zz els | sat mode: N=0/1 u/s | - | 11 | inv | CR-bit | Rc=1: pred-result CR sel | - | 11 | inv | els RC1 | Rc=0: pred-result z/nonz | - """ - - # for LD/ST-indexed (RA+RB): - """ - | 0-1 | 2 | 3 4 | description | - | --- | --- |---------|----------------------------- | - | 00 | SEA | dz sz | normal mode | - | 01 | SEA | dz sz | strided (scalar only source) | - | 10 | N | dz sz | sat mode: N=0/1 u/s | - | 11 | inv | CR-bit | Rc=1: pred-result CR sel | - | 11 | inv | dz RC1 | Rc=0: pred-result z/nonz | - """ - - # and leaving out branches and cr_ops for now because they're - # under development - """ TODO branches and cr_ops - """ - - if is_bc: - sv_mode = int(svp64_rm.mode[0, 1]) - if src_zero: - svp64_rm.branch.sz = 1 - - else: - ###################################### - # "element-strided" mode, ldst_idx - if sv_mode == 0b01 and is_ldst_idx: - mode |= src_zero << SVP64MODE.SZ # predicate zeroing - mode |= dst_zero << SVP64MODE.DZ # predicate zeroing - mode |= sea << SVP64MODE.SEA # el-strided - - ###################################### - # "normal" mode - elif sv_mode is None: - mode |= src_zero << SVP64MODE.SZ # predicate zeroing - mode |= dst_zero << SVP64MODE.DZ # predicate zeroing - if is_ldst: - # TODO: for now, LD/ST-indexed is ignored. - mode |= ldst_elstride << SVP64MODE.ELS_NORMAL # el-strided - else: - # TODO, reduce and subvector mode - # 00 1 dz CRM reduce mode (mapreduce), SUBVL=1 - # 00 1 SVM CRM subvector reduce mode, SUBVL>1 - pass - sv_mode = 0b00 - - ###################################### - # ldst-immediate "post" (and "load-fault-first" modes) - elif sv_mode == 0b00 and ldst_postinc == 1: # (or ldst_ld_ffirst) - mode |= (0b1 << SVP64MODE.LDI_POST) # sets bit 2 - mode |= (ldst_postinc << SVP64MODE.LDI_PI) # sets post-inc - - ###################################### - # "mapreduce" modes - elif sv_mode == 0b00: - mode |= (0b1 << SVP64MODE.REDUCE) # sets mapreduce - assert dst_zero == 0, "dest-zero not allowed in mapreduce mode" - if reverse_gear: - mode |= (0b1 << SVP64MODE.RG) # sets Reverse-gear mode - if mapreduce_crm: - mode |= (0b1 << SVP64MODE.CRM) # sets CRM mode - assert rc_mode, "CRM only allowed when Rc=1" - # bit of weird encoding to jam zero-pred or SVM mode in. - # SVM mode can be enabled only when SUBVL=2/3/4 (vec2/3/4) - if subvl == 0: - mode |= dst_zero << SVP64MODE.DZ # predicate zeroing - - ###################################### - # "failfirst" modes - elif failfirst is not False and not is_cr: # sv_mode == 0b01: - assert src_zero == 0, "dest-zero not allowed in failfirst mode" - if failfirst == 'RC1': - mode |= (0b1 << SVP64MODE.RC1) # sets RC1 mode - mode |= (dst_zero << SVP64MODE.DZ) # predicate dst-zeroing - assert rc_mode == False, "ffirst RC1 only ok when Rc=0" - elif failfirst == '~RC1': - mode |= (0b1 << SVP64MODE.RC1) # sets RC1 mode - mode |= (dst_zero << SVP64MODE.DZ) # predicate dst-zeroing - mode |= (0b1 << SVP64MODE.INV) # ... with inversion - assert rc_mode == False, "ffirst RC1 only ok when Rc=0" - else: - assert dst_zero == 0, "dst-zero not allowed in ffirst BO" - assert rc_mode, "ffirst BO only possible when Rc=1" - mode |= (failfirst << SVP64MODE.BO_LSB) # set BO - - # (crops is really different) - elif failfirst is not False and is_cr: - if failfirst in ['RC1', '~RC1']: - mode |= (src_zero << SVP64MODE.SZ) # predicate src-zeroing - mode |= (dst_zero << SVP64MODE.DZ) # predicate dst-zeroing - if failfirst == '~RC1': - mode |= (0b1 << SVP64MODE.INV) # ... with inversion - else: - assert dst_zero == src_zero, "dz must equal sz in ffirst BO" - mode |= (failfirst << SVP64MODE.BO_LSB) # set BO - svp64_rm.cr_op.zz = dst_zero - if vli: - sv_mode |= 1 # set VLI in LSB of 2-bit mode - #svp64_rm.cr_op.vli = 1 - - ###################################### - # "saturation" modes - elif sv_mode == 0b10: - mode |= src_zero << SVP64MODE.SZ # predicate zeroing - mode |= dst_zero << SVP64MODE.DZ # predicate zeroing - mode |= (saturation << SVP64MODE.N) # signed/us saturation - - ###################################### - # "predicate-result" modes. err... code-duplication from ffirst - elif sv_mode == 0b11: - assert src_zero == 0, "dest-zero not allowed in predresult mode" - if predresult == 'RC1': - mode |= (0b1 << SVP64MODE.RC1) # sets RC1 mode - mode |= (dst_zero << SVP64MODE.DZ) # predicate dst-zeroing - assert rc_mode == False, "pr-mode RC1 only ok when Rc=0" - elif predresult == '~RC1': - mode |= (0b1 << SVP64MODE.RC1) # sets RC1 mode - mode |= (dst_zero << SVP64MODE.DZ) # predicate dst-zeroing - mode |= (0b1 << SVP64MODE.INV) # ... with inversion - assert rc_mode == False, "pr-mode RC1 only ok when Rc=0" - else: - assert dst_zero == 0, "dst-zero not allowed in pr-mode BO" - assert rc_mode, "pr-mode BO only possible when Rc=1" - mode |= (predresult << SVP64MODE.BO_LSB) # set BO - - # whewww.... modes all done :) - # now put into svp64_rm, but respect MSB0 order - if sv_mode & 1: - mode |= (0b1 << SVP64MODE.MOD2_LSB) - if sv_mode & 2: - mode |= (0b1 << SVP64MODE.MOD2_MSB) - - if sea: - mode |= (0b1 << SVP64MODE.SEA) - - # this is a mess. really look forward to replacing it with Insn DB - if not is_bc: - svp64_rm.mode = mode # mode: bits 19-23 - if vli and not is_cr: - svp64_rm.normal.ffrc0.VLi = 1 - - # put in predicate masks into svp64_rm - if ptype == '2P': - svp64_rm.smask = smask # source pred: bits 16-18 - - # put in elwidths unless cr - if not is_cr: - svp64_rm.ewsrc = srcwid # srcwid: bits 6-7 - svp64_rm.elwidth = destwid # destwid: bits 4-5 - - svp64_rm.mmode = mmode # mask mode: bit 0 - svp64_rm.mask = pmask # 1-pred: bits 1-3 - svp64_rm.subvl = subvl # and subvl: bits 8-9 - - # nice debug printout. (and now for something completely different) - # https://youtu.be/u0WOIwlXE9g?t=146 - svp64_rm_value = int(svp64_rm) - log("svp64_rm", hex(svp64_rm_value), bin(svp64_rm_value)) - log(" mmode 0 :", bin(mmode)) - log(" pmask 1-3 :", bin(pmask)) - log(" dstwid 4-5 :", bin(destwid)) - log(" srcwid 6-7 :", bin(srcwid)) - log(" subvl 8-9 :", bin(subvl)) - log(" mode 19-23:", bin(svp64_rm.mode)) - offs = 2 if etype == 'EXTRA2' else 3 # 2 or 3 bits - for idx, sv_extra in extras.items(): - if idx is None: - continue - if idx[0] == 'imm': - continue - srcdest, idx, duplicate = idx - start = (10+idx*offs) - end = start + offs-1 - log(" extra%d %2d-%2d:" % (idx, start, end), - bin(sv_extra)) - if ptype == '2P': - log(" smask 16-17:", bin(smask)) - log() - - # update prefix PO and ID (aka PID) - svp64_prefix.PO = 0x1 - svp64_prefix.id = 0b11 - - # fiinally yield the svp64 prefix and the thingy. v3.0b opcode - rc = '.' if rc_mode else '' - yield ".long 0x%08x" % int(svp64_prefix) - log(v30b_op, v30b_newfields) - - v30b_op_rc = v30b_op - if not v30b_op.endswith('.'): - v30b_op_rc += rc - - record = None - if os.environ.get("INSNDB"): - record = DB[opcode] - if record is not None: - insn = WordInstruction.assemble(db=DB, - entry=opcode, arguments=fields) - yield from insn.disassemble(db=DB, style=Style.LEGACY) - else: - if not v30b_op.endswith('.'): - v30b_op += rc - yield "%s %s" % (v30b_op, ", ".join(v30b_newfields)) - for (name, span) in svp64_insn.traverse("SVP64"): - value = svp64_insn.storage[span] - log(name, f"{value.value:0{value.bits}b}", span) - log("new v3.0B fields", v30b_op, v30b_newfields) + raise AssemblerError(insn_no_comments) def translate(self, lst): for insn in lst: -- 2.30.2