1793958c9STaylor Simpson#!/usr/bin/env python3 2793958c9STaylor Simpson 3793958c9STaylor Simpson## 4e2be9a5cSTaylor Simpson## Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved. 5793958c9STaylor Simpson## 6793958c9STaylor Simpson## This program is free software; you can redistribute it and/or modify 7793958c9STaylor Simpson## it under the terms of the GNU General Public License as published by 8793958c9STaylor Simpson## the Free Software Foundation; either version 2 of the License, or 9793958c9STaylor Simpson## (at your option) any later version. 10793958c9STaylor Simpson## 11793958c9STaylor Simpson## This program is distributed in the hope that it will be useful, 12793958c9STaylor Simpson## but WITHOUT ANY WARRANTY; without even the implied warranty of 13793958c9STaylor Simpson## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14793958c9STaylor Simpson## GNU General Public License for more details. 15793958c9STaylor Simpson## 16793958c9STaylor Simpson## You should have received a copy of the GNU General Public License 17793958c9STaylor Simpson## along with this program; if not, see <http://www.gnu.org/licenses/>. 18793958c9STaylor Simpson## 19793958c9STaylor Simpson 20793958c9STaylor Simpsonimport sys 21793958c9STaylor Simpsonimport re 22793958c9STaylor Simpsonimport string 23793958c9STaylor Simpson 24793958c9STaylor Simpsonbehdict = {} # tag ->behavior 25793958c9STaylor Simpsonsemdict = {} # tag -> semantics 26793958c9STaylor Simpsonattribdict = {} # tag -> attributes 27793958c9STaylor Simpsonmacros = {} # macro -> macro information... 28793958c9STaylor Simpsonattribinfo = {} # Register information and misc 29793958c9STaylor Simpsontags = [] # list of all tags 30793958c9STaylor Simpsonoverrides = {} # tags with helper overrides 31e71fdc4fSAlessandro Di Federicoidef_parser_enabled = {} # tags enabled for idef-parser 32793958c9STaylor Simpson 33793958c9STaylor Simpson# We should do this as a hash for performance, 34793958c9STaylor Simpson# but to keep order let's keep it as a list. 35793958c9STaylor Simpsondef uniquify(seq): 36793958c9STaylor Simpson seen = set() 37793958c9STaylor Simpson seen_add = seen.add 38793958c9STaylor Simpson return [x for x in seq if x not in seen and not seen_add(x)] 39793958c9STaylor Simpson 40793958c9STaylor Simpsonregre = re.compile( 41793958c9STaylor Simpson r"((?<!DUP)[MNORCPQXSGVZA])([stuvwxyzdefg]+)([.]?[LlHh]?)(\d+S?)") 42793958c9STaylor Simpsonimmre = re.compile(r"[#]([rRsSuUm])(\d+)(?:[:](\d+))?") 43793958c9STaylor Simpsonreg_or_immre = \ 44793958c9STaylor Simpson re.compile(r"(((?<!DUP)[MNRCOPQXSGVZA])([stuvwxyzdefg]+)" + \ 45793958c9STaylor Simpson "([.]?[LlHh]?)(\d+S?))|([#]([rRsSuUm])(\d+)[:]?(\d+)?)") 46793958c9STaylor Simpsonrelimmre = re.compile(r"[#]([rR])(\d+)(?:[:](\d+))?") 47793958c9STaylor Simpsonabsimmre = re.compile(r"[#]([sSuUm])(\d+)(?:[:](\d+))?") 48793958c9STaylor Simpson 49793958c9STaylor Simpsonfinished_macros = set() 50793958c9STaylor Simpson 51793958c9STaylor Simpsondef expand_macro_attribs(macro,allmac_re): 52793958c9STaylor Simpson if macro.key not in finished_macros: 53793958c9STaylor Simpson # Get a list of all things that might be macros 54793958c9STaylor Simpson l = allmac_re.findall(macro.beh) 55793958c9STaylor Simpson for submacro in l: 56793958c9STaylor Simpson if not submacro: continue 57793958c9STaylor Simpson if not macros[submacro]: 58793958c9STaylor Simpson raise Exception("Couldn't find macro: <%s>" % l) 59793958c9STaylor Simpson macro.attribs |= expand_macro_attribs( 60793958c9STaylor Simpson macros[submacro], allmac_re) 61793958c9STaylor Simpson finished_macros.add(macro.key) 62793958c9STaylor Simpson return macro.attribs 63793958c9STaylor Simpson 64793958c9STaylor Simpson# When qemu needs an attribute that isn't in the imported files, 65793958c9STaylor Simpson# we'll add it here. 66793958c9STaylor Simpsondef add_qemu_macro_attrib(name, attrib): 67793958c9STaylor Simpson macros[name].attribs.add(attrib) 68793958c9STaylor Simpson 69793958c9STaylor Simpsonimmextre = re.compile(r'f(MUST_)?IMMEXT[(]([UuSsRr])') 70613653e5STaylor Simpson 71613653e5STaylor Simpsondef is_cond_jump(tag): 72613653e5STaylor Simpson if tag == 'J2_rte': 73613653e5STaylor Simpson return False 74613653e5STaylor Simpson if ('A_HWLOOP0_END' in attribdict[tag] or 75613653e5STaylor Simpson 'A_HWLOOP1_END' in attribdict[tag]): 76613653e5STaylor Simpson return False 77613653e5STaylor Simpson return \ 78613653e5STaylor Simpson re.compile(r"(if.*fBRANCH)|(if.*fJUMPR)").search(semdict[tag]) != None 79613653e5STaylor Simpson 80613653e5STaylor Simpsondef is_cond_call(tag): 81613653e5STaylor Simpson return re.compile(r"(if.*fCALL)").search(semdict[tag]) != None 82613653e5STaylor Simpson 83793958c9STaylor Simpsondef calculate_attribs(): 84793958c9STaylor Simpson add_qemu_macro_attrib('fREAD_PC', 'A_IMPLICIT_READS_PC') 85793958c9STaylor Simpson add_qemu_macro_attrib('fTRAP', 'A_IMPLICIT_READS_PC') 86793958c9STaylor Simpson add_qemu_macro_attrib('fWRITE_P0', 'A_WRITES_PRED_REG') 87793958c9STaylor Simpson add_qemu_macro_attrib('fWRITE_P1', 'A_WRITES_PRED_REG') 88793958c9STaylor Simpson add_qemu_macro_attrib('fWRITE_P2', 'A_WRITES_PRED_REG') 89793958c9STaylor Simpson add_qemu_macro_attrib('fWRITE_P3', 'A_WRITES_PRED_REG') 90b9dd6ff9STaylor Simpson add_qemu_macro_attrib('fSET_OVERFLOW', 'A_IMPLICIT_WRITES_USR') 91b9dd6ff9STaylor Simpson add_qemu_macro_attrib('fSET_LPCFG', 'A_IMPLICIT_WRITES_USR') 92e2be9a5cSTaylor Simpson add_qemu_macro_attrib('fSTORE', 'A_SCALAR_STORE') 93793958c9STaylor Simpson 94793958c9STaylor Simpson # Recurse down macros, find attributes from sub-macros 95793958c9STaylor Simpson macroValues = list(macros.values()) 96793958c9STaylor Simpson allmacros_restr = "|".join(set([ m.re.pattern for m in macroValues ])) 97793958c9STaylor Simpson allmacros_re = re.compile(allmacros_restr) 98793958c9STaylor Simpson for macro in macroValues: 99793958c9STaylor Simpson expand_macro_attribs(macro,allmacros_re) 100793958c9STaylor Simpson # Append attributes to all instructions 101793958c9STaylor Simpson for tag in tags: 102793958c9STaylor Simpson for macname in allmacros_re.findall(semdict[tag]): 103793958c9STaylor Simpson if not macname: continue 104793958c9STaylor Simpson macro = macros[macname] 105793958c9STaylor Simpson attribdict[tag] |= set(macro.attribs) 106793958c9STaylor Simpson # Figure out which instructions write predicate registers 107793958c9STaylor Simpson tagregs = get_tagregs() 108793958c9STaylor Simpson for tag in tags: 109793958c9STaylor Simpson regs = tagregs[tag] 110793958c9STaylor Simpson for regtype, regid, toss, numregs in regs: 111793958c9STaylor Simpson if regtype == "P" and is_written(regid): 112793958c9STaylor Simpson attribdict[tag].add('A_WRITES_PRED_REG') 113613653e5STaylor Simpson # Mark conditional jumps and calls 114613653e5STaylor Simpson # Not all instructions are properly marked with A_CONDEXEC 115613653e5STaylor Simpson for tag in tags: 116613653e5STaylor Simpson if is_cond_jump(tag) or is_cond_call(tag): 117613653e5STaylor Simpson attribdict[tag].add('A_CONDEXEC') 118793958c9STaylor Simpson 119793958c9STaylor Simpsondef SEMANTICS(tag, beh, sem): 120793958c9STaylor Simpson #print tag,beh,sem 121793958c9STaylor Simpson behdict[tag] = beh 122793958c9STaylor Simpson semdict[tag] = sem 123793958c9STaylor Simpson attribdict[tag] = set() 124793958c9STaylor Simpson tags.append(tag) # dicts have no order, this is for order 125793958c9STaylor Simpson 126793958c9STaylor Simpsondef ATTRIBUTES(tag, attribstring): 127793958c9STaylor Simpson attribstring = \ 128793958c9STaylor Simpson attribstring.replace("ATTRIBS","").replace("(","").replace(")","") 129793958c9STaylor Simpson if not attribstring: 130793958c9STaylor Simpson return 131793958c9STaylor Simpson attribs = attribstring.split(",") 132793958c9STaylor Simpson for attrib in attribs: 133793958c9STaylor Simpson attribdict[tag].add(attrib.strip()) 134793958c9STaylor Simpson 135793958c9STaylor Simpsonclass Macro(object): 136793958c9STaylor Simpson __slots__ = ['key','name', 'beh', 'attribs', 're'] 137793958c9STaylor Simpson def __init__(self, name, beh, attribs): 138793958c9STaylor Simpson self.key = name 139793958c9STaylor Simpson self.name = name 140793958c9STaylor Simpson self.beh = beh 141793958c9STaylor Simpson self.attribs = set(attribs) 142793958c9STaylor Simpson self.re = re.compile("\\b" + name + "\\b") 143793958c9STaylor Simpson 144793958c9STaylor Simpsondef MACROATTRIB(macname,beh,attribstring): 145793958c9STaylor Simpson attribstring = attribstring.replace("(","").replace(")","") 146793958c9STaylor Simpson if attribstring: 147793958c9STaylor Simpson attribs = attribstring.split(",") 148793958c9STaylor Simpson else: 149793958c9STaylor Simpson attribs = [] 150793958c9STaylor Simpson macros[macname] = Macro(macname,beh,attribs) 151793958c9STaylor Simpson 152793958c9STaylor Simpsondef compute_tag_regs(tag): 153793958c9STaylor Simpson return uniquify(regre.findall(behdict[tag])) 154793958c9STaylor Simpson 155793958c9STaylor Simpsondef compute_tag_immediates(tag): 156793958c9STaylor Simpson return uniquify(immre.findall(behdict[tag])) 157793958c9STaylor Simpson 158793958c9STaylor Simpson## 159793958c9STaylor Simpson## tagregs is the main data structure we'll use 160793958c9STaylor Simpson## tagregs[tag] will contain the registers used by an instruction 161793958c9STaylor Simpson## Within each entry, we'll use the regtype and regid fields 162793958c9STaylor Simpson## regtype can be one of the following 163793958c9STaylor Simpson## C control register 164793958c9STaylor Simpson## N new register value 165793958c9STaylor Simpson## P predicate register 166793958c9STaylor Simpson## R GPR register 167793958c9STaylor Simpson## M modifier register 168144da357STaylor Simpson## Q HVX predicate vector 169144da357STaylor Simpson## V HVX vector register 170144da357STaylor Simpson## O HVX new vector register 171793958c9STaylor Simpson## regid can be one of the following 172793958c9STaylor Simpson## d, e destination register 173793958c9STaylor Simpson## dd destination register pair 174793958c9STaylor Simpson## s, t, u, v, w source register 175793958c9STaylor Simpson## ss, tt, uu, vv source register pair 176793958c9STaylor Simpson## x, y read-write register 177793958c9STaylor Simpson## xx, yy read-write register pair 178793958c9STaylor Simpson## 179793958c9STaylor Simpsondef get_tagregs(): 180793958c9STaylor Simpson return dict(zip(tags, list(map(compute_tag_regs, tags)))) 181793958c9STaylor Simpson 182793958c9STaylor Simpsondef get_tagimms(): 183793958c9STaylor Simpson return dict(zip(tags, list(map(compute_tag_immediates, tags)))) 184793958c9STaylor Simpson 185793958c9STaylor Simpsondef is_pair(regid): 186793958c9STaylor Simpson return len(regid) == 2 187793958c9STaylor Simpson 188793958c9STaylor Simpsondef is_single(regid): 189793958c9STaylor Simpson return len(regid) == 1 190793958c9STaylor Simpson 191793958c9STaylor Simpsondef is_written(regid): 192793958c9STaylor Simpson return regid[0] in "dexy" 193793958c9STaylor Simpson 194793958c9STaylor Simpsondef is_writeonly(regid): 195793958c9STaylor Simpson return regid[0] in "de" 196793958c9STaylor Simpson 197793958c9STaylor Simpsondef is_read(regid): 198793958c9STaylor Simpson return regid[0] in "stuvwxy" 199793958c9STaylor Simpson 200793958c9STaylor Simpsondef is_readwrite(regid): 201793958c9STaylor Simpson return regid[0] in "xy" 202793958c9STaylor Simpson 203793958c9STaylor Simpsondef is_scalar_reg(regtype): 204793958c9STaylor Simpson return regtype in "RPC" 205793958c9STaylor Simpson 206144da357STaylor Simpsondef is_hvx_reg(regtype): 207144da357STaylor Simpson return regtype in "VQ" 208144da357STaylor Simpson 209793958c9STaylor Simpsondef is_old_val(regtype, regid, tag): 210793958c9STaylor Simpson return regtype+regid+'V' in semdict[tag] 211793958c9STaylor Simpson 212793958c9STaylor Simpsondef is_new_val(regtype, regid, tag): 213793958c9STaylor Simpson return regtype+regid+'N' in semdict[tag] 214793958c9STaylor Simpson 215793958c9STaylor Simpsondef need_slot(tag): 21640085901STaylor Simpson if (('A_CONDEXEC' in attribdict[tag] and 21740085901STaylor Simpson 'A_JUMP' not in attribdict[tag]) or 218793958c9STaylor Simpson 'A_STORE' in attribdict[tag] or 219793958c9STaylor Simpson 'A_LOAD' in attribdict[tag]): 220793958c9STaylor Simpson return 1 221793958c9STaylor Simpson else: 222793958c9STaylor Simpson return 0 223793958c9STaylor Simpson 224793958c9STaylor Simpsondef need_part1(tag): 225793958c9STaylor Simpson return re.compile(r"fPART1").search(semdict[tag]) 226793958c9STaylor Simpson 227793958c9STaylor Simpsondef need_ea(tag): 228793958c9STaylor Simpson return re.compile(r"\bEA\b").search(semdict[tag]) 229793958c9STaylor Simpson 23040085901STaylor Simpsondef need_PC(tag): 23140085901STaylor Simpson return 'A_IMPLICIT_READS_PC' in attribdict[tag] 23240085901STaylor Simpson 233613653e5STaylor Simpsondef helper_needs_next_PC(tag): 234613653e5STaylor Simpson return 'A_CALL' in attribdict[tag] 235613653e5STaylor Simpson 236fb67c2bfSTaylor Simpsondef need_pkt_has_multi_cof(tag): 237fb67c2bfSTaylor Simpson return 'A_COF' in attribdict[tag] 238fb67c2bfSTaylor Simpson 239793958c9STaylor Simpsondef skip_qemu_helper(tag): 240793958c9STaylor Simpson return tag in overrides.keys() 241793958c9STaylor Simpson 242144da357STaylor Simpsondef is_tmp_result(tag): 243144da357STaylor Simpson return ('A_CVI_TMP' in attribdict[tag] or 244144da357STaylor Simpson 'A_CVI_TMP_DST' in attribdict[tag]) 245144da357STaylor Simpson 246144da357STaylor Simpsondef is_new_result(tag): 247144da357STaylor Simpson return ('A_CVI_NEW' in attribdict[tag]) 248144da357STaylor Simpson 249e71fdc4fSAlessandro Di Federicodef is_idef_parser_enabled(tag): 250e71fdc4fSAlessandro Di Federico return tag in idef_parser_enabled 251e71fdc4fSAlessandro Di Federico 252793958c9STaylor Simpsondef imm_name(immlett): 253793958c9STaylor Simpson return "%siV" % immlett 254793958c9STaylor Simpson 255793958c9STaylor Simpsondef read_semantics_file(name): 256793958c9STaylor Simpson eval_line = "" 257793958c9STaylor Simpson for line in open(name, 'rt').readlines(): 258793958c9STaylor Simpson if not line.startswith("#"): 259793958c9STaylor Simpson eval_line += line 260793958c9STaylor Simpson if line.endswith("\\\n"): 261793958c9STaylor Simpson eval_line.rstrip("\\\n") 262793958c9STaylor Simpson else: 263793958c9STaylor Simpson eval(eval_line.strip()) 264793958c9STaylor Simpson eval_line = "" 265793958c9STaylor Simpson 266793958c9STaylor Simpsondef read_attribs_file(name): 267793958c9STaylor Simpson attribre = re.compile(r'DEF_ATTRIB\(([A-Za-z0-9_]+), ([^,]*), ' + 268793958c9STaylor Simpson r'"([A-Za-z0-9_\.]*)", "([A-Za-z0-9_\.]*)"\)') 269793958c9STaylor Simpson for line in open(name, 'rt').readlines(): 270793958c9STaylor Simpson if not attribre.match(line): 271793958c9STaylor Simpson continue 272793958c9STaylor Simpson (attrib_base,descr,rreg,wreg) = attribre.findall(line)[0] 273793958c9STaylor Simpson attrib_base = 'A_' + attrib_base 274793958c9STaylor Simpson attribinfo[attrib_base] = {'rreg':rreg, 'wreg':wreg, 'descr':descr} 275793958c9STaylor Simpson 276793958c9STaylor Simpsondef read_overrides_file(name): 277793958c9STaylor Simpson overridere = re.compile("#define fGEN_TCG_([A-Za-z0-9_]+)\(.*") 278793958c9STaylor Simpson for line in open(name, 'rt').readlines(): 279793958c9STaylor Simpson if not overridere.match(line): 280793958c9STaylor Simpson continue 281793958c9STaylor Simpson tag = overridere.findall(line)[0] 282793958c9STaylor Simpson overrides[tag] = True 283e71fdc4fSAlessandro Di Federico 284e71fdc4fSAlessandro Di Federicodef read_idef_parser_enabled_file(name): 285e71fdc4fSAlessandro Di Federico global idef_parser_enabled 286e71fdc4fSAlessandro Di Federico with open(name, "r") as idef_parser_enabled_file: 287e71fdc4fSAlessandro Di Federico lines = idef_parser_enabled_file.read().strip().split("\n") 288e71fdc4fSAlessandro Di Federico idef_parser_enabled = set(lines) 289