X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fopenpower%2Fsv%2Fsv_analysis.py;h=332a0b2db0abb03b54be0608f0c993825a75e5b9;hb=938d5ab27813e0a79f99814dca2d6c462c4629b8;hp=d6dfa167ff1bed8fb737f2c86f9315508a1fdd86;hpb=43b06b819839a3b84a76fb69a5b3690918e6b381;p=openpower-isa.git diff --git a/src/openpower/sv/sv_analysis.py b/src/openpower/sv/sv_analysis.py index d6dfa167..332a0b2d 100644 --- a/src/openpower/sv/sv_analysis.py +++ b/src/openpower/sv/sv_analysis.py @@ -11,6 +11,14 @@ # It finds .csv files in the directory isatables/ # then goes through the categories and creates svp64 CSV augmentation # tables on a per-opcode basis +# +# NOTE: this program is effectively part of the Simple-V Specification. +# it encapsulates the relationships of what can be SVP64-encoded and +# holds all of the information on how to encode and decode SVP64. +# By auto-generating tables that go into the Simple-V Specification +# this program *is* the specification. do not be confused just because +# it is in python: if you do not understand please ask questions and +# help create patches with explanatory comments. import argparse import csv @@ -25,6 +33,29 @@ from openpower.decoder.power_enums import find_wiki_file, get_csv from openpower.util import log +# Ignore those containing: valid test sprs +def glob_valid_csvs(root): + def check_csv(fname): + _, name = os.path.split(fname) + if '-' in name: + return False + if 'valid' in fname: + return False + if 'test' in fname: + return False + if fname.endswith('insndb.csv'): + return False + if fname.endswith('sprs.csv'): + return False + if fname.endswith('minor_19_valid.csv'): + return False + if 'RM' in fname: + return False + return True + + yield from filter(check_csv, glob(root)) + + # Write an array of dictionaries to the CSV file name: def write_csv(name, items, headers): file_path = find_wiki_file(name) @@ -66,6 +97,11 @@ tablecols = ['unit', 'in', 'outcnt', 'CR in', 'CR out', 'imm' def create_key(row): + """ create an equivalent of a database key by which it is possible + to easily categorise an instruction. later this category is used + to decide what kind of EXTRA encoding is to be done because the + key contains the total number of input and output registers + """ res = OrderedDict() #print ("row", row) for key in keycolumns: @@ -129,15 +165,6 @@ def create_key(row): else: res['imm'] = '' - # pack/unpack, start with LDST with immediate for now - if (res['imm'] == '1' and res['unit'] == 'LDST' and - ((res['in'] == '1' and res['outcnt'] == '1') or # LD-imm - (res['in'] == '2' and res['outcnt'] == '0'))): # ST-imm - #print ("PU", res, row) - res['PU'] = "1" - else: - res['PU'] = '' - return res # @@ -155,6 +182,9 @@ def tformat(d): def keyname(row): + """converts a key into a readable string. anything null or zero + is skipped, shortening the readable string + """ res = [] if row['unit'] != 'OTHER': res.append(row['unit']) @@ -173,9 +203,6 @@ def keyname(row): res.append("CRo") elif 'imm' in row and row['imm']: res.append("imm") - if 'PU' in row and row['PU']: - #print("key", row) - res.append("PU") return '-'.join(res) @@ -255,7 +282,7 @@ class Format(enum.Enum): }[self](lines) -def process_csvs(format): +def read_csvs(): csvs = {} csvs_svp64 = {} bykey = {} @@ -265,31 +292,11 @@ def process_csvs(format): insns = {} # dictionary of CSV row, by instruction insn_to_csv = {} - print("# Draft SVP64 Power ISA register 'profile's") - print('') - print("this page is auto-generated, do not edit") - print("created by http://libre-soc.org/openpower/sv_analysis.py") - print('') - # Expand that (all .csv files) pth = find_wiki_file("*.csv") # Ignore those containing: valid test sprs - for fname in glob(pth): - #print("sv analysis checking", fname) - _, name = os.path.split(fname) - if '-' in name: - continue - if 'valid' in fname: - continue - if 'test' in fname: - continue - if fname.endswith('sprs.csv'): - continue - if fname.endswith('minor_19_valid.csv'): - continue - if 'RM' in fname: - continue + for fname in glob_valid_csvs(pth): csvname = os.path.split(fname)[1] csvname_ = csvname.split(".")[0] # csvname is something like: minor_59.csv, fname the whole path @@ -307,13 +314,21 @@ def process_csvs(format): continue # skip pseudo-alias lxxxbr if insn_name in ['mcrxr', 'mcrxrx', 'darn']: continue - if insn_name in ['bctar', 'bcctr']: + if insn_name in ['bctar', 'bcctr']: # for now. TODO continue if 'rfid' in insn_name: continue - if insn_name in ['setvl', ]: # SVP64 opcodes + if 'addpcis' in insn_name: # skip for now continue + # sv.bc is being classified as 2P-2S-1D by mistake due to SPRs + if insn_name.startswith('bc'): + # whoops: remove out reg (SPRs CTR etc) + row['in1'] = 'NONE' + row['in2'] = 'NONE' + row['in3'] = 'NONE' + row['out'] = 'NONE' + insns[(insn_name, condition)] = row # accumulate csv data insn_to_csv[insn_name] = csvname_ # CSV file name by instruction dkey = create_key(row) @@ -336,8 +351,306 @@ def process_csvs(format): primarykeys = list(primarykeys) primarykeys.sort() + return (csvs, csvs_svp64, primarykeys, bykey, insn_to_csv, insns, + dictkeys, immediates) + + +def regs_profile(insn, res): + """get a more detailed register profile: 1st operand is RA, + 2nd is RB, etc. etc + """ + regs = [] + for k in ['in1', 'in2', 'in3', 'out', 'CR in', 'CR out']: + if insn[k].startswith('CONST'): + res[k] = '' + regs.append('') + else: + res[k] = insn[k] + if insn[k] == 'RA_OR_ZERO': + regs.append('RA') + elif insn[k] != 'NONE': + regs.append(insn[k]) + else: + regs.append('') + return regs + + +def extra_classifier(insn_name, value, name, res, regs): + """extra_classifier: creates the SVP64.RM EXTRA2/3 classification. + there is very little space (9 bits) to mark register operands + (RT RA RB, BA BB, BFA, FRS etc.) with the "extra" information + needed to tell if *EACH* operand (of which there can be up to five!) + is Vectorised, and whether its numbering is extended into the + 0..127 range rather than the limited 3/5 bit of Scalar v3.0 Power ISA. + + thus begins the rather tedious but by-rote examination of EVERY + Scalar instruction, working out how best to tell a decoder how to + extend the registers. EXTRA2 can have up to 4 slots (of 2 bit each) + where due to RM.EXTRA being 9 bits, EXTRA3 can have up to 3 slots + (of 3 bit each). the index REGNAME says which slot the register + named REGNAME must read its decoding from. d: means destination, + s: means source. some are *shared slots* especially LDST update. + some Rc=1 ops have the CR0/CR1 as a co-result which is also + obviously Vectorised if the result is Vectorised. + + it is actually quite straightforward but the sheer quantity of + Scalar Power ISA instructions made it prudent to do this in an + intelligent way, almost by-rote, by analysing the register profiles. + """ + # for LD/ST FP, use FRT/FRS not RT/RS, and use CR1 not CR0 + if insn_name.startswith("lf"): + dRT = 'd:FRT' + dCR = 'd:CR1' + else: + dRT = 'd:RT' + dCR = 'd:CR0' + if insn_name.startswith("stf"): + sRS = 's:FRS' + dCR = 'd:CR1' + else: + sRS = 's:RS' + dCR = 'd:CR0' + + # sigh now the fun begins. this isn't the sanest way to do it + # but the patterns are pretty regular. we start with the "profile" + # because that determines how much space is available (total num + # regs to decode) then if necessary begin apecialising either + # by the instruction name or through more detailed register + # profiling. example: + # if regs == ['RA', '', '', 'RT', '', '']: + # is in the order in1 in2 in3 out1 out2 Rc=1 + + # ******** + # start with LD/ST + + if value == 'LDSTRM-2P-1S1D': + res['Etype'] = 'EXTRA3' # RM EXTRA3 type + res['0'] = dRT # RT: Rdest_EXTRA3 + res['1'] = 's:RA' # RA: Rsrc1_EXTRA3 + + elif value == 'LDSTRM-2P-1S2D': + res['Etype'] = 'EXTRA2' # RM EXTRA2 type + res['0'] = dRT # RT: Rdest_EXTRA3 + res['1'] = 'd:RA' # RA: Rdest2_EXTRA2 + res['2'] = 's:RA' # RA: Rsrc1_EXTRA2 + + elif value == 'LDSTRM-2P-2S': + # stw, std, sth, stb + res['Etype'] = 'EXTRA3' # RM EXTRA3 type + res['0'] = sRS # RS: Rdest1_EXTRA3 + res['1'] = 's:RA' # RA: Rsrc1_EXTRA3 + + elif value == 'LDSTRM-2P-2S1D': + if 'st' in insn_name and 'x' not in insn_name: # stwu/stbu etc + res['Etype'] = 'EXTRA2' # RM EXTRA2 type + res['0'] = 'd:RA' # RA: Rdest1_EXTRA2 + res['1'] = sRS # RS: Rdsrc1_EXTRA2 + res['2'] = 's:RA' # RA: Rsrc2_EXTRA2 + elif 'st' in insn_name and 'x' in insn_name: # stwux + res['Etype'] = 'EXTRA2' # RM EXTRA2 type + res['0'] = 'd:RA' # RA: Rdest1_EXTRA2 + # RS: Rdest2_EXTRA2, RA: Rsrc1_EXTRA2 + res['1'] = "%s;%s" % (sRS, 's:RA') + res['2'] = 's:RB' # RB: Rsrc2_EXTRA2 + elif 'u' in insn_name: # ldux etc. + res['Etype'] = 'EXTRA2' # RM EXTRA2 type + res['0'] = dRT # RT: Rdest1_EXTRA2 + res['1'] = 'd:RA' # RA: Rdest2_EXTRA2 + res['2'] = 's:RB' # RB: Rsrc1_EXTRA2 + else: + res['Etype'] = 'EXTRA2' # RM EXTRA2 type + res['0'] = dRT # RT: Rdest1_EXTRA2 + res['1'] = 's:RA' # RA: Rsrc1_EXTRA2 + res['2'] = 's:RB' # RB: Rsrc2_EXTRA2 + + elif value == 'LDSTRM-2P-3S': + res['Etype'] = 'EXTRA2' # RM EXTRA2 type + if 'cx' in insn_name: + res['0'] = "%s;%s" % (sRS, dCR) # RS: Rsrc1_EXTRA2 CR0: dest + else: + res['0'] = sRS # RS: Rsrc1_EXTRA2 + res['1'] = 's:RA' # RA: Rsrc2_EXTRA2 + res['2'] = 's:RB' # RA: Rsrc3_EXTRA2 + + # ********** + # now begins,arithmetic + + elif value == 'RM-2P-1S1D': + res['Etype'] = 'EXTRA3' # RM EXTRA3 type + if insn_name == 'mtspr': + res['0'] = 'd:SPR' # SPR: Rdest1_EXTRA3 + res['1'] = 's:RS' # RS: Rsrc1_EXTRA3 + elif insn_name == 'mfspr': + res['0'] = 'd:RS' # RS: Rdest1_EXTRA3 + res['1'] = 's:SPR' # SPR: Rsrc1_EXTRA3 + elif name == 'CRio' and insn_name == 'mcrf': + res['0'] = 'd:BF' # BFA: Rdest1_EXTRA3 + res['1'] = 's:BFA' # BFA: Rsrc1_EXTRA3 + elif 'mfcr' in insn_name or 'mfocrf' in insn_name: + res['0'] = 'd:RT' # RT: Rdest1_EXTRA3 + res['1'] = 's:CR' # CR: Rsrc1_EXTRA3 + elif insn_name == 'setb': + res['0'] = 'd:RT' # RT: Rdest1_EXTRA3 + res['1'] = 's:BFA' # BFA: Rsrc1_EXTRA3 + elif insn_name.startswith('cmp'): # cmpi + res['0'] = 'd:BF' # BF: Rdest1_EXTRA3 + res['1'] = 's:RA' # RA: Rsrc1_EXTRA3 + elif regs == ['RA', '', '', 'RT', '', '']: + res['0'] = 'd:RT' # RT: Rdest1_EXTRA3 + res['1'] = 's:RA' # RA: Rsrc1_EXTRA3 + elif regs == ['RA', '', '', 'RT', '', 'CR0']: + res['0'] = 'd:RT;d:CR0' # RT,CR0: Rdest1_EXTRA3 + res['1'] = 's:RA' # RA: Rsrc1_EXTRA3 + elif (regs == ['RS', '', '', 'RA', '', 'CR0'] or + regs == ['', '', 'RS', 'RA', '', 'CR0']): + res['0'] = 'd:RA;d:CR0' # RA,CR0: Rdest1_EXTRA3 + res['1'] = 's:RS' # RS: Rsrc1_EXTRA3 + elif regs == ['RS', '', '', 'RA', '', '']: + res['0'] = 'd:RA' # RA: Rdest1_EXTRA3 + res['1'] = 's:RS' # RS: Rsrc1_EXTRA3 + elif regs == ['', 'FRB', '', 'FRT', '0', 'CR1']: + res['0'] = 'd:FRT;d:CR1' # FRT,CR1: Rdest1_EXTRA3 + res['1'] = 's:FRA' # FRA: Rsrc1_EXTRA3 + elif regs == ['', 'FRB', '', '', '', 'CR1']: + res['0'] = 'd:CR1' # CR1: Rdest1_EXTRA3 + res['1'] = 's:FRB' # FRA: Rsrc1_EXTRA3 + elif regs == ['', 'FRB', '', '', '', 'BF']: + res['0'] = 'd:BF' # BF: Rdest1_EXTRA3 + res['1'] = 's:FRB' # FRA: Rsrc1_EXTRA3 + elif regs == ['', 'FRB', '', 'FRT', '', 'CR1']: + res['0'] = 'd:FRT;d:CR1' # FRT,CR1: Rdest1_EXTRA3 + res['1'] = 's:FRB' # FRB: Rsrc1_EXTRA3 + elif insn_name == 'fishmv': + # an overwrite instruction + res['0'] = 'd:FRS' # FRS: Rdest1_EXTRA3 + res['1'] = 's:FRS' # FRS: Rsrc1_EXTRA3 + elif insn_name == 'setvl': + res['0'] = 'd:RT' # RT: Rdest1_EXTRA3 + res['1'] = 's:RA' # RS: Rsrc1_EXTRA3 + else: + res['0'] = 'TODO' + print("regs TODO", insn_name, regs) + + elif value == 'RM-1P-2S1D': + res['Etype'] = 'EXTRA3' # RM EXTRA3 type + if insn_name.startswith('cr'): + res['0'] = 'd:BT' # BT: Rdest1_EXTRA3 + res['1'] = 's:BA' # BA: Rsrc1_EXTRA3 + res['2'] = 's:BB' # BB: Rsrc2_EXTRA3 + elif regs == ['FRA', '', 'FRC', 'FRT', '', 'CR1']: + res['0'] = 'd:FRT;d:CR1' # FRT,CR1: Rdest1_EXTRA3 + res['1'] = 's:FRA' # FRA: Rsrc1_EXTRA3 + res['2'] = 's:FRC' # FRC: Rsrc1_EXTRA3 + # should be for fcmp + elif regs == ['FRA', 'FRB', '', '', '', 'BF']: + res['0'] = 'd:BF' # BF: Rdest1_EXTRA3 + res['1'] = 's:FRA' # FRA: Rsrc1_EXTRA3 + res['2'] = 's:FRB' # FRB: Rsrc1_EXTRA3 + elif regs == ['FRA', 'FRB', '', 'FRT', '', '']: + res['0'] = 'd:FRT' # FRT: Rdest1_EXTRA3 + res['1'] = 's:FRA' # FRA: Rsrc1_EXTRA3 + res['2'] = 's:FRB' # FRB: Rsrc1_EXTRA3 + elif regs == ['FRA', 'FRB', '', 'FRT', '', 'CR1']: + res['0'] = 'd:FRT;d:CR1' # FRT,CR1: Rdest1_EXTRA3 + res['1'] = 's:FRA' # FRA: Rsrc1_EXTRA3 + res['2'] = 's:FRB' # FRB: Rsrc1_EXTRA3 + elif regs == ['FRA', 'RB', '', 'FRT', '', 'CR1']: + res['0'] = 'd:FRT;d:CR1' # FRT,CR1: Rdest1_EXTRA3 + res['1'] = 's:FRA' # FRA: Rsrc1_EXTRA3 + res['2'] = 's:RB' # RB: Rsrc1_EXTRA3 + elif name == '2R-1W' or insn_name == 'cmpb': # cmpb + if insn_name in ['bpermd', 'cmpb']: + res['0'] = 'd:RA' # RA: Rdest1_EXTRA3 + res['1'] = 's:RS' # RS: Rsrc1_EXTRA3 + else: + res['0'] = 'd:RT' # RT: Rdest1_EXTRA3 + res['1'] = 's:RA' # RA: Rsrc1_EXTRA3 + res['2'] = 's:RB' # RB: Rsrc1_EXTRA3 + elif insn_name.startswith('cmp'): # cmp + res['0'] = 'd:BF' # BF: Rdest1_EXTRA3 + res['1'] = 's:RA' # RA: Rsrc1_EXTRA3 + res['2'] = 's:RB' # RB: Rsrc1_EXTRA3 + elif (regs == ['', 'RB', 'RS', 'RA', '', 'CR0'] or + regs == ['RS', 'RB', '', 'RA', '', 'CR0']): + res['0'] = 'd:RA;d:CR0' # RA,CR0: Rdest1_EXTRA3 + res['1'] = 's:RB' # RB: Rsrc1_EXTRA3 + res['2'] = 's:RS' # RS: Rsrc1_EXTRA3 + elif regs == ['RA', 'RB', '', 'RT', '', 'CR0']: + res['0'] = 'd:RT;d:CR0' # RT,CR0: Rdest1_EXTRA3 + res['1'] = 's:RA' # RA: Rsrc1_EXTRA3 + res['2'] = 's:RB' # RB: Rsrc1_EXTRA3 + elif regs == ['RA', '', 'RS', 'RA', '', 'CR0']: + res['0'] = 'd:RA;d:CR0' # RA,CR0: Rdest1_EXTRA3 + res['1'] = 's:RA' # RA: Rsrc1_EXTRA3 + res['2'] = 's:RS' # RS: Rsrc1_EXTRA3 + else: + res['0'] = 'TODO' + + elif value == 'RM-2P-2S1D': + res['Etype'] = 'EXTRA2' # RM EXTRA2 type + if insn_name.startswith('mt'): # mtcrf + res['0'] = 'd:CR' # CR: Rdest1_EXTRA2 + res['1'] = 's:RS' # RS: Rsrc1_EXTRA2 + res['2'] = 's:CR' # CR: Rsrc2_EXTRA2 + else: + res['0'] = 'TODO' + + elif value == 'RM-1P-3S1D': + res['Etype'] = 'EXTRA2' # RM EXTRA2 type + if regs == ['RA', 'RB', 'RC', 'RT', '', '']: # madd* + res['0'] = 'd:RT' # RT,CR0: Rdest1_EXTRA2 + res['1'] = 's:RA' # RA: Rsrc1_EXTRA2 + res['2'] = 's:RB' # RT: Rsrc2_EXTRA2 + res['3'] = 's:RC' # RT: Rsrc3_EXTRA2 + elif regs == ['RA', 'RB', 'RC', 'RT', '', 'CR0']: # pcdec + res['0'] = 'd:RT;d:CR0' # RT,CR0: Rdest1_EXTRA2 + res['1'] = 's:RA' # RA: Rsrc1_EXTRA2 + res['2'] = 's:RB' # RT: Rsrc2_EXTRA2 + res['3'] = 's:RC' # RT: Rsrc3_EXTRA2 + elif regs == ['RA', 'RB', 'RT', 'RT', '', 'CR0']: # overwrite 3-in + res['0'] = 'd:RT;d:CR0' # RT,CR0: Rdest1_EXTRA2 + res['1'] = 's:RA' # RA: Rsrc1_EXTRA2 + res['2'] = 's:RB' # RT: Rsrc2_EXTRA2 + res['3'] = 's:RT' # RT: Rsrc3_EXTRA2 + elif insn_name == 'isel': + res['0'] = 'd:RT' # RT: Rdest1_EXTRA2 + res['1'] = 's:RA' # RA: Rsrc1_EXTRA2 + res['2'] = 's:RB' # RT: Rsrc2_EXTRA2 + res['3'] = 's:BC' # BC: Rsrc3_EXTRA2 + else: # fmadd* + res['0'] = 'd:FRT;d:CR1' # FRT, CR1: Rdest1_EXTRA2 + res['1'] = 's:FRA' # FRA: Rsrc1_EXTRA2 + res['2'] = 's:FRB' # FRB: Rsrc2_EXTRA2 + res['3'] = 's:FRC' # FRC: Rsrc3_EXTRA2 + + elif value == 'RM-1P-1D': + res['Etype'] = 'EXTRA3' # RM EXTRA3 type + if insn_name == 'svstep': + res['0'] = 'd:RT;d:CR0' # RT,CR0: Rdest1_EXTRA3 + if insn_name == 'fmvis': + res['0'] = 'd:FRS' # FRS: Rdest1_EXTRA3 + + # HACK! thos should be RM-1P-1S butvthere is a bug with sv.bc + elif value == 'RM-2P-1S': + res['Etype'] = 'EXTRA3' # RM EXTRA3 type + if insn_name.startswith('bc'): + res['0'] = 's:BI' # BI: Rsrc1_EXTRA3 + + +def process_csvs(format): + + print("# Draft SVP64 Power ISA register 'profile's") + print('') + print("this page is auto-generated, do not edit") + print("created by http://libre-soc.org/openpower/sv_analysis.py") + print('') + + (csvs, csvs_svp64, primarykeys, bykey, insn_to_csv, insns, + dictkeys, immediates) = read_csvs() + # mapping to old SVPrefix "Forms" mapsto = {'3R-1W-CRo': 'RM-1P-3S1D', + '3R-1W': 'RM-1P-3S1D', '2R-1W-CRio': 'RM-1P-2S1D', '2R-1W-CRi': 'RM-1P-3S1D', '2R-1W-CRo': 'RM-1P-2S1D', @@ -359,15 +672,13 @@ def process_csvs(format): '1W-CRi': 'RM-2P-1S1D', 'CRio': 'RM-2P-1S1D', 'CR=2R1W': 'RM-1P-2S1D', - 'CRi': 'non-SV', + 'CRi': 'RM-2P-1S', # HACK, bc here, it should be 1P 'imm': 'non-SV', '': 'non-SV', 'LDST-2R-imm': 'LDSTRM-2P-2S', - 'LDST-2R-imm-PU': 'LDSTRM-2P-2S-PU', 'LDST-2R-1W-imm': 'LDSTRM-2P-2S1D', 'LDST-2R-1W': 'LDSTRM-2P-2S1D', 'LDST-2R-2W': 'LDSTRM-2P-2S1D', - 'LDST-1R-1W-imm-PU': 'LDSTRM-2P-1S1D-PU', 'LDST-1R-1W-imm': 'LDSTRM-2P-1S1D', 'LDST-1R-2W-imm': 'LDSTRM-2P-1S2D', 'LDST-3R': 'LDSTRM-2P-3S', @@ -428,10 +739,9 @@ def process_csvs(format): # create a CSV file, per category, with SV "augmentation" info # XXX note: 'out2' not added here, needs to be added to CSV files # KEEP TRACK OF THESE https://bugs.libre-soc.org/show_bug.cgi?id=619 - csvcols = ['insn', 'mode', 'CONDITIONS', 'Ptype', 'Etype',] + csvcols = ['insn', 'mode', 'CONDITIONS', 'Ptype', 'Etype', 'SM'] csvcols += ['0', '1', '2', '3'] csvcols += ['in1', 'in2', 'in3', 'out', 'CR in', 'CR out'] # temporary - csvcols += ['PU'] # pack/unpack for key in primarykeys: # get the decoded key containing row-analysis, and name/value dkey = dictkeys[key] @@ -478,253 +788,36 @@ def process_csvs(format): # set the SVP64 mode to NORMAL, LDST, BRANCH or CR crops = ['mfcr', 'mfocrf', 'mtcrf', 'mtocrf', - ] + ] mode = 'NORMAL' if value.startswith('LDST'): - mode = 'LDST' + if 'x' in insn_name: # Indexed detection + mode = 'LDST_IDX' + else: + mode = 'LDST_IMM' elif insn_name.startswith('bc'): mode = 'BRANCH' - elif insn_name.startswith('cr') or insn_name in crops: + elif insn_name.startswith('cmp') or insn_name.startswith('cr') or insn_name in crops: mode = 'CROP' res['mode'] = mode - # Pack/Unpack - if value.endswith('PU'): - pack = '1' - else: - pack = '0' - res['PU'] = pack - - # temporary useful info - regs = [] - for k in ['in1', 'in2', 'in3', 'out', 'CR in', 'CR out']: - if insn[k].startswith('CONST'): - res[k] = '' - regs.append('') - else: - res[k] = insn[k] - if insn[k] == 'RA_OR_ZERO': - regs.append('RA') - elif insn[k] != 'NONE': - regs.append(insn[k]) - else: - regs.append('') + # create a register profile list (update res row as well) + regs = regs_profile(insn, res) #print("regs", insn_name, regs) - - # for LD/ST FP, use FRT/FRS not RT/RS, and use CR1 not CR0 - if insn_name.startswith("lf"): - dRT = 'd:FRT' - dCR = 'd:CR1' - else: - dRT = 'd:RT' - dCR = 'd:CR0' - if insn_name.startswith("stf"): - sRS = 's:FRS' - dCR = 'd:CR1' + extra_classifier(insn_name, value, name, res, regs) + + # source-mask is hard to detect, it's part of RM-nn-nn. + # to make disassembler easier, create a yes/no decision here + # see https://libre-soc.org/openpower/sv/svp64/#extra_remap + # MASK_SRC + vstripped = value.replace("LDST", "") + if vstripped in ['RM-2P-1S1D', 'RM-2P-2S', + 'RM-2P-2S1D', 'RM-2P-1S2D', 'RM-2P-3S', + ]: + res['SM'] = 'EN' else: - sRS = 's:RS' - dCR = 'd:CR0' - - # sigh now the fun begins. this isn't the sanest way to do it - # but the patterns are pretty regular. - - if value == 'LDSTRM-2P-1S1D-PU': # pack/unpack LD - res['Etype'] = 'EXTRA2' # RM EXTRA2 type - res['0'] = dRT # RT: Rdest_EXTRA2 - res['1'] = 's:RA' # RA: Rsrc1_EXTRA2 - - elif value == 'LDSTRM-2P-1S1D': - res['Etype'] = 'EXTRA3' # RM EXTRA3 type - res['0'] = dRT # RT: Rdest_EXTRA3 - res['1'] = 's:RA' # RA: Rsrc1_EXTRA3 - - elif value == 'LDSTRM-2P-1S2D': - res['Etype'] = 'EXTRA2' # RM EXTRA2 type - res['0'] = dRT # RT: Rdest_EXTRA3 - res['1'] = 'd:RA' # RA: Rdest2_EXTRA2 - res['2'] = 's:RA' # RA: Rsrc1_EXTRA2 - - elif value == 'LDSTRM-2P-2S-PU': # pack/unpack ST - # stw, std, sth, stb - res['Etype'] = 'EXTRA2' # RM EXTRA2 type - res['0'] = sRS # RS: Rdest1_EXTRA2 - res['1'] = 's:RA' # RA: Rsrc1_EXTRA2 - - elif value == 'LDSTRM-2P-2S': - # stw, std, sth, stb - res['Etype'] = 'EXTRA3' # RM EXTRA3 type - res['0'] = sRS # RS: Rdest1_EXTRA3 - res['1'] = 's:RA' # RA: Rsrc1_EXTRA3 - - elif value == 'LDSTRM-2P-2S1D': - if 'st' in insn_name and 'x' not in insn_name: # stwu/stbu etc - res['Etype'] = 'EXTRA2' # RM EXTRA2 type - res['0'] = 'd:RA' # RA: Rdest1_EXTRA2 - res['1'] = sRS # RS: Rdsrc1_EXTRA2 - res['2'] = 's:RA' # RA: Rsrc2_EXTRA2 - elif 'st' in insn_name and 'x' in insn_name: # stwux - res['Etype'] = 'EXTRA2' # RM EXTRA2 type - res['0'] = 'd:RA' # RA: Rdest1_EXTRA2 - # RS: Rdest2_EXTRA2, RA: Rsrc1_EXTRA2 - res['1'] = "%s;%s" % (sRS, 's:RA') - res['2'] = 's:RB' # RB: Rsrc2_EXTRA2 - elif 'u' in insn_name: # ldux etc. - res['Etype'] = 'EXTRA2' # RM EXTRA2 type - res['0'] = dRT # RT: Rdest1_EXTRA2 - res['1'] = 'd:RA' # RA: Rdest2_EXTRA2 - res['2'] = 's:RB' # RB: Rsrc1_EXTRA2 - else: - res['Etype'] = 'EXTRA2' # RM EXTRA2 type - res['0'] = dRT # RT: Rdest1_EXTRA2 - res['1'] = 's:RA' # RA: Rsrc1_EXTRA2 - res['2'] = 's:RB' # RB: Rsrc2_EXTRA2 - - elif value == 'LDSTRM-2P-3S': - res['Etype'] = 'EXTRA2' # RM EXTRA2 type - if 'cx' in insn_name: - res['0'] = "%s;%s" % (sRS, dCR) # RS: Rsrc1_EXTRA2 CR0: dest - else: - res['0'] = sRS # RS: Rsrc1_EXTRA2 - res['1'] = 's:RA' # RA: Rsrc2_EXTRA2 - res['2'] = 's:RB' # RA: Rsrc3_EXTRA2 - - elif value == 'RM-2P-1S1D': - res['Etype'] = 'EXTRA3' # RM EXTRA3 type - if insn_name == 'mtspr': - res['0'] = 'd:SPR' # SPR: Rdest1_EXTRA3 - res['1'] = 's:RS' # RS: Rsrc1_EXTRA3 - elif insn_name == 'mfspr': - res['0'] = 'd:RS' # RS: Rdest1_EXTRA3 - res['1'] = 's:SPR' # SPR: Rsrc1_EXTRA3 - elif name == 'CRio' and insn_name == 'mcrf': - res['0'] = 'd:BF' # BFA: Rdest1_EXTRA3 - res['1'] = 's:BFA' # BFA: Rsrc1_EXTRA3 - elif 'mfcr' in insn_name or 'mfocrf' in insn_name: - res['0'] = 'd:RT' # RT: Rdest1_EXTRA3 - res['1'] = 's:CR' # CR: Rsrc1_EXTRA3 - elif insn_name == 'setb': - res['0'] = 'd:RT' # RT: Rdest1_EXTRA3 - res['1'] = 's:BFA' # BFA: Rsrc1_EXTRA3 - elif insn_name.startswith('cmp'): # cmpi - res['0'] = 'd:BF' # BF: Rdest1_EXTRA3 - res['1'] = 's:RA' # RA: Rsrc1_EXTRA3 - elif regs == ['RA', '', '', 'RT', '', '']: - res['0'] = 'd:RT' # RT: Rdest1_EXTRA3 - res['1'] = 's:RA' # RA: Rsrc1_EXTRA3 - elif regs == ['RA', '', '', 'RT', '', 'CR0']: - res['0'] = 'd:RT;d:CR0' # RT,CR0: Rdest1_EXTRA3 - res['1'] = 's:RA' # RA: Rsrc1_EXTRA3 - elif (regs == ['RS', '', '', 'RA', '', 'CR0'] or - regs == ['', '', 'RS', 'RA', '', 'CR0']): - res['0'] = 'd:RA;d:CR0' # RA,CR0: Rdest1_EXTRA3 - res['1'] = 's:RS' # RS: Rsrc1_EXTRA3 - elif regs == ['RS', '', '', 'RA', '', '']: - res['0'] = 'd:RA' # RA: Rdest1_EXTRA3 - res['1'] = 's:RS' # RS: Rsrc1_EXTRA3 - elif regs == ['', 'FRB', '', 'FRT', '0', 'CR1']: - res['0'] = 'd:FRT;d:CR1' # FRT,CR1: Rdest1_EXTRA3 - res['1'] = 's:FRA' # FRA: Rsrc1_EXTRA3 - elif regs == ['', 'FRB', '', '', '', 'CR1']: - res['0'] = 'd:CR1' # CR1: Rdest1_EXTRA3 - res['1'] = 's:FRB' # FRA: Rsrc1_EXTRA3 - elif regs == ['', 'FRB', '', '', '', 'BF']: - res['0'] = 'd:BF' # BF: Rdest1_EXTRA3 - res['1'] = 's:FRB' # FRA: Rsrc1_EXTRA3 - elif regs == ['', 'FRB', '', 'FRT', '', 'CR1']: - res['0'] = 'd:FRT;d:CR1' # FRT,CR1: Rdest1_EXTRA3 - res['1'] = 's:FRB' # FRB: Rsrc1_EXTRA3 - elif insn_name.startswith('bc'): - res['0'] = 'd:BI' # BI: Rdest1_EXTRA3 - res['1'] = 's:BI' # BI: Rsrc1_EXTRA3 - else: - res['0'] = 'TODO' - - elif value == 'RM-1P-2S1D': - res['Etype'] = 'EXTRA3' # RM EXTRA3 type - if insn_name.startswith('cr'): - res['0'] = 'd:BT' # BT: Rdest1_EXTRA3 - res['1'] = 's:BA' # BA: Rsrc1_EXTRA3 - res['2'] = 's:BB' # BB: Rsrc2_EXTRA3 - elif regs == ['FRA', '', 'FRC', 'FRT', '', 'CR1']: - res['0'] = 'd:FRT;d:CR1' # FRT,CR1: Rdest1_EXTRA3 - res['1'] = 's:FRA' # FRA: Rsrc1_EXTRA3 - res['2'] = 's:FRC' # FRC: Rsrc1_EXTRA3 - # should be for fcmp - elif regs == ['FRA', 'FRB', '', '', '', 'BF']: - res['0'] = 'd:BF' # BF: Rdest1_EXTRA3 - res['1'] = 's:FRA' # FRA: Rsrc1_EXTRA3 - res['2'] = 's:FRB' # FRB: Rsrc1_EXTRA3 - elif regs == ['FRA', 'FRB', '', 'FRT', '', '']: - res['0'] = 'd:FRT' # FRT: Rdest1_EXTRA3 - res['1'] = 's:FRA' # FRA: Rsrc1_EXTRA3 - res['2'] = 's:FRB' # FRB: Rsrc1_EXTRA3 - elif regs == ['FRA', 'FRB', '', 'FRT', '', 'CR1']: - res['0'] = 'd:FRT;d:CR1' # FRT,CR1: Rdest1_EXTRA3 - res['1'] = 's:FRA' # FRA: Rsrc1_EXTRA3 - res['2'] = 's:FRB' # FRB: Rsrc1_EXTRA3 - elif name == '2R-1W' or insn_name == 'cmpb': # cmpb - if insn_name in ['bpermd', 'cmpb']: - res['0'] = 'd:RA' # RA: Rdest1_EXTRA3 - res['1'] = 's:RS' # RS: Rsrc1_EXTRA3 - else: - res['0'] = 'd:RT' # RT: Rdest1_EXTRA3 - res['1'] = 's:RA' # RA: Rsrc1_EXTRA3 - res['2'] = 's:RB' # RB: Rsrc1_EXTRA3 - elif insn_name.startswith('cmp'): # cmp - res['0'] = 'd:BF' # BF: Rdest1_EXTRA3 - res['1'] = 's:RA' # RA: Rsrc1_EXTRA3 - res['2'] = 's:RB' # RB: Rsrc1_EXTRA3 - elif (regs == ['', 'RB', 'RS', 'RA', '', 'CR0'] or - regs == ['RS', 'RB', '', 'RA', '', 'CR0']): - res['0'] = 'd:RA;d:CR0' # RA,CR0: Rdest1_EXTRA3 - res['1'] = 's:RB' # RB: Rsrc1_EXTRA3 - res['2'] = 's:RS' # RS: Rsrc1_EXTRA3 - elif regs == ['RA', 'RB', '', 'RT', '', 'CR0']: - res['0'] = 'd:RT;d:CR0' # RT,CR0: Rdest1_EXTRA3 - res['1'] = 's:RA' # RA: Rsrc1_EXTRA3 - res['2'] = 's:RB' # RB: Rsrc1_EXTRA3 - elif regs == ['RA', '', 'RS', 'RA', '', 'CR0']: - res['0'] = 'd:RA;d:CR0' # RA,CR0: Rdest1_EXTRA3 - res['1'] = 's:RA' # RA: Rsrc1_EXTRA3 - res['2'] = 's:RS' # RS: Rsrc1_EXTRA3 - else: - res['0'] = 'TODO' - - elif value == 'RM-2P-2S1D': - res['Etype'] = 'EXTRA2' # RM EXTRA2 type - if insn_name.startswith('mt'): # mtcrf - res['0'] = 'd:CR' # CR: Rdest1_EXTRA2 - res['1'] = 's:RS' # RS: Rsrc1_EXTRA2 - res['2'] = 's:CR' # CR: Rsrc2_EXTRA2 - else: - res['0'] = 'TODO' - - elif value == 'RM-1P-3S1D': - res['Etype'] = 'EXTRA2' # RM EXTRA2 type - if regs == ['RA', 'RB', 'RT', 'RT', '', 'CR0']: - res['0'] = 'd:RT;d:CR0' # RT,CR0: Rdest1_EXTRA2 - res['1'] = 's:RA' # RA: Rsrc1_EXTRA2 - res['2'] = 's:RB' # RT: Rsrc2_EXTRA2 - res['3'] = 's:RT' # RT: Rsrc3_EXTRA2 - elif insn_name == 'isel': - res['0'] = 'd:RT' # RT: Rdest1_EXTRA2 - res['1'] = 's:RA' # RA: Rsrc1_EXTRA2 - res['2'] = 's:RB' # RT: Rsrc2_EXTRA2 - res['3'] = 's:BC' # BC: Rsrc3_EXTRA2 - else: - res['0'] = 'd:FRT;d:CR1' # FRT, CR1: Rdest1_EXTRA2 - res['1'] = 's:FRA' # FRA: Rsrc1_EXTRA2 - res['2'] = 's:FRB' # FRB: Rsrc2_EXTRA2 - res['3'] = 's:FRC' # FRC: Rsrc3_EXTRA2 - - elif value == 'RM-1P-1D': - res['Etype'] = 'EXTRA3' # RM EXTRA3 type - if insn_name == 'svstep': - res['0'] = 'd:RT;d:CR0' # RT,CR0: Rdest1_EXTRA3 - if insn_name == 'fmvis': - res['0'] = 'd:FRS' # FRS: Rdest1_EXTRA3 - + res['SM'] = 'NO' # add to svp64 csvs # for k in ['in1', 'in2', 'in3', 'out', 'CR in', 'CR out']: # del res[k] @@ -746,8 +839,8 @@ def process_csvs(format): if value == '-': continue from time import sleep - print ("WARNING, filename '-' should NOT exist. instrs missing") - print ("TODO: fix this (and put in the bugreport number here)") + print("WARNING, filename '-' should NOT exist. instrs missing") + print("TODO: fix this (and put in the bugreport number here)") sleep(2) # print out svp64 tables by category print("## %s" % value) @@ -773,24 +866,10 @@ def process_csvs(format): pth = find_wiki_file("*.csv") # Ignore those containing: valid test sprs - for fname in glob(pth): - #print("post-checking", fname) - _, name = os.path.split(fname) - if '-' in name: - continue - if 'valid' in fname: - continue - if 'test' in fname: - continue - if fname.endswith('sprs.csv'): - continue - if fname.endswith('minor_19_valid.csv'): - continue - if 'RM' in fname: - continue + for fname in glob_valid_csvs(pth): svp64_csv = svt.get_svp64_csv(fname) - csvcols = ['insn', 'mode', 'Ptype', 'Etype'] + csvcols = ['insn', 'mode', 'Ptype', 'Etype', 'SM'] csvcols += ['in1', 'in2', 'in3', 'out', 'out2', 'CR in', 'CR out'] if format is Format.VHDL: