1793958c9STaylor Simpson#!/usr/bin/env python3 2793958c9STaylor Simpson 3793958c9STaylor Simpson## 4e28b77a6STaylor Simpson## Copyright(c) 2019-2023 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 335bb322e2SMarco Liebel 34793958c9STaylor Simpson# We should do this as a hash for performance, 35793958c9STaylor Simpson# but to keep order let's keep it as a list. 36793958c9STaylor Simpsondef uniquify(seq): 37793958c9STaylor Simpson seen = set() 38793958c9STaylor Simpson seen_add = seen.add 39793958c9STaylor Simpson return [x for x in seq if x not in seen and not seen_add(x)] 40793958c9STaylor Simpson 415bb322e2SMarco Liebel 425bb322e2SMarco Liebelregre = re.compile(r"((?<!DUP)[MNORCPQXSGVZA])([stuvwxyzdefg]+)([.]?[LlHh]?)(\d+S?)") 43793958c9STaylor Simpsonimmre = re.compile(r"[#]([rRsSuUm])(\d+)(?:[:](\d+))?") 445bb322e2SMarco Liebelreg_or_immre = re.compile( 455bb322e2SMarco Liebel r"(((?<!DUP)[MNRCOPQXSGVZA])([stuvwxyzdefg]+)" 465bb322e2SMarco Liebel + "([.]?[LlHh]?)(\d+S?))|([#]([rRsSuUm])(\d+)[:]?(\d+)?)" 475bb322e2SMarco Liebel) 48793958c9STaylor Simpsonrelimmre = re.compile(r"[#]([rR])(\d+)(?:[:](\d+))?") 49793958c9STaylor Simpsonabsimmre = re.compile(r"[#]([sSuUm])(\d+)(?:[:](\d+))?") 50793958c9STaylor Simpson 51793958c9STaylor Simpsonfinished_macros = set() 52793958c9STaylor Simpson 535bb322e2SMarco Liebel 54793958c9STaylor Simpsondef expand_macro_attribs(macro, allmac_re): 55793958c9STaylor Simpson if macro.key not in finished_macros: 56793958c9STaylor Simpson # Get a list of all things that might be macros 57793958c9STaylor Simpson l = allmac_re.findall(macro.beh) 58793958c9STaylor Simpson for submacro in l: 595bb322e2SMarco Liebel if not submacro: 605bb322e2SMarco Liebel continue 61793958c9STaylor Simpson if not macros[submacro]: 62cd6c4edfSMarco Liebel raise Exception(f"Couldn't find macro: <{l}>") 635bb322e2SMarco Liebel macro.attribs |= expand_macro_attribs(macros[submacro], allmac_re) 64793958c9STaylor Simpson finished_macros.add(macro.key) 65793958c9STaylor Simpson return macro.attribs 66793958c9STaylor Simpson 675bb322e2SMarco Liebel 68793958c9STaylor Simpson# When qemu needs an attribute that isn't in the imported files, 69793958c9STaylor Simpson# we'll add it here. 70793958c9STaylor Simpsondef add_qemu_macro_attrib(name, attrib): 71793958c9STaylor Simpson macros[name].attribs.add(attrib) 72793958c9STaylor Simpson 735bb322e2SMarco Liebel 745bb322e2SMarco Liebelimmextre = re.compile(r"f(MUST_)?IMMEXT[(]([UuSsRr])") 755bb322e2SMarco Liebel 76613653e5STaylor Simpson 77613653e5STaylor Simpsondef is_cond_jump(tag): 785bb322e2SMarco Liebel if tag == "J2_rte": 79613653e5STaylor Simpson return False 805bb322e2SMarco Liebel if "A_HWLOOP0_END" in attribdict[tag] or "A_HWLOOP1_END" in attribdict[tag]: 81613653e5STaylor Simpson return False 825bb322e2SMarco Liebel return re.compile(r"(if.*fBRANCH)|(if.*fJUMPR)").search(semdict[tag]) != None 835bb322e2SMarco Liebel 84613653e5STaylor Simpson 85613653e5STaylor Simpsondef is_cond_call(tag): 86613653e5STaylor Simpson return re.compile(r"(if.*fCALL)").search(semdict[tag]) != None 87613653e5STaylor Simpson 885bb322e2SMarco Liebel 89793958c9STaylor Simpsondef calculate_attribs(): 905bb322e2SMarco Liebel add_qemu_macro_attrib("fREAD_PC", "A_IMPLICIT_READS_PC") 915bb322e2SMarco Liebel add_qemu_macro_attrib("fTRAP", "A_IMPLICIT_READS_PC") 925bb322e2SMarco Liebel add_qemu_macro_attrib("fWRITE_P0", "A_WRITES_PRED_REG") 935bb322e2SMarco Liebel add_qemu_macro_attrib("fWRITE_P1", "A_WRITES_PRED_REG") 945bb322e2SMarco Liebel add_qemu_macro_attrib("fWRITE_P2", "A_WRITES_PRED_REG") 955bb322e2SMarco Liebel add_qemu_macro_attrib("fWRITE_P3", "A_WRITES_PRED_REG") 965bb322e2SMarco Liebel add_qemu_macro_attrib("fSET_OVERFLOW", "A_IMPLICIT_WRITES_USR") 975bb322e2SMarco Liebel add_qemu_macro_attrib("fSET_LPCFG", "A_IMPLICIT_WRITES_USR") 985bb322e2SMarco Liebel add_qemu_macro_attrib("fLOAD", "A_SCALAR_LOAD") 995bb322e2SMarco Liebel add_qemu_macro_attrib("fSTORE", "A_SCALAR_STORE") 100793958c9STaylor Simpson 101793958c9STaylor Simpson # Recurse down macros, find attributes from sub-macros 102793958c9STaylor Simpson macroValues = list(macros.values()) 103793958c9STaylor Simpson allmacros_restr = "|".join(set([m.re.pattern for m in macroValues])) 104793958c9STaylor Simpson allmacros_re = re.compile(allmacros_restr) 105793958c9STaylor Simpson for macro in macroValues: 106793958c9STaylor Simpson expand_macro_attribs(macro, allmacros_re) 107793958c9STaylor Simpson # Append attributes to all instructions 108793958c9STaylor Simpson for tag in tags: 109793958c9STaylor Simpson for macname in allmacros_re.findall(semdict[tag]): 1105bb322e2SMarco Liebel if not macname: 1115bb322e2SMarco Liebel continue 112793958c9STaylor Simpson macro = macros[macname] 113793958c9STaylor Simpson attribdict[tag] |= set(macro.attribs) 114793958c9STaylor Simpson # Figure out which instructions write predicate registers 115793958c9STaylor Simpson tagregs = get_tagregs() 116793958c9STaylor Simpson for tag in tags: 117793958c9STaylor Simpson regs = tagregs[tag] 118793958c9STaylor Simpson for regtype, regid, toss, numregs in regs: 119793958c9STaylor Simpson if regtype == "P" and is_written(regid): 1205bb322e2SMarco Liebel attribdict[tag].add("A_WRITES_PRED_REG") 121613653e5STaylor Simpson # Mark conditional jumps and calls 122613653e5STaylor Simpson # Not all instructions are properly marked with A_CONDEXEC 123613653e5STaylor Simpson for tag in tags: 124613653e5STaylor Simpson if is_cond_jump(tag) or is_cond_call(tag): 1255bb322e2SMarco Liebel attribdict[tag].add("A_CONDEXEC") 1265bb322e2SMarco Liebel 127793958c9STaylor Simpson 128793958c9STaylor Simpsondef SEMANTICS(tag, beh, sem): 129793958c9STaylor Simpson # print tag,beh,sem 130793958c9STaylor Simpson behdict[tag] = beh 131793958c9STaylor Simpson semdict[tag] = sem 132793958c9STaylor Simpson attribdict[tag] = set() 133793958c9STaylor Simpson tags.append(tag) # dicts have no order, this is for order 134793958c9STaylor Simpson 1355bb322e2SMarco Liebel 136793958c9STaylor Simpsondef ATTRIBUTES(tag, attribstring): 1375bb322e2SMarco Liebel attribstring = attribstring.replace("ATTRIBS", "").replace("(", "").replace(")", "") 138793958c9STaylor Simpson if not attribstring: 139793958c9STaylor Simpson return 140793958c9STaylor Simpson attribs = attribstring.split(",") 141793958c9STaylor Simpson for attrib in attribs: 142793958c9STaylor Simpson attribdict[tag].add(attrib.strip()) 143793958c9STaylor Simpson 1445bb322e2SMarco Liebel 145793958c9STaylor Simpsonclass Macro(object): 1465bb322e2SMarco Liebel __slots__ = ["key", "name", "beh", "attribs", "re"] 1475bb322e2SMarco Liebel 148793958c9STaylor Simpson def __init__(self, name, beh, attribs): 149793958c9STaylor Simpson self.key = name 150793958c9STaylor Simpson self.name = name 151793958c9STaylor Simpson self.beh = beh 152793958c9STaylor Simpson self.attribs = set(attribs) 153793958c9STaylor Simpson self.re = re.compile("\\b" + name + "\\b") 154793958c9STaylor Simpson 1555bb322e2SMarco Liebel 156793958c9STaylor Simpsondef MACROATTRIB(macname, beh, attribstring): 157793958c9STaylor Simpson attribstring = attribstring.replace("(", "").replace(")", "") 158793958c9STaylor Simpson if attribstring: 159793958c9STaylor Simpson attribs = attribstring.split(",") 160793958c9STaylor Simpson else: 161793958c9STaylor Simpson attribs = [] 162793958c9STaylor Simpson macros[macname] = Macro(macname, beh, attribs) 163793958c9STaylor Simpson 1645bb322e2SMarco Liebel 165793958c9STaylor Simpsondef compute_tag_regs(tag): 166793958c9STaylor Simpson return uniquify(regre.findall(behdict[tag])) 167793958c9STaylor Simpson 1685bb322e2SMarco Liebel 169793958c9STaylor Simpsondef compute_tag_immediates(tag): 170793958c9STaylor Simpson return uniquify(immre.findall(behdict[tag])) 171793958c9STaylor Simpson 1725bb322e2SMarco Liebel 173793958c9STaylor Simpson## 174793958c9STaylor Simpson## tagregs is the main data structure we'll use 175793958c9STaylor Simpson## tagregs[tag] will contain the registers used by an instruction 176793958c9STaylor Simpson## Within each entry, we'll use the regtype and regid fields 177793958c9STaylor Simpson## regtype can be one of the following 178793958c9STaylor Simpson## C control register 179793958c9STaylor Simpson## N new register value 180793958c9STaylor Simpson## P predicate register 181793958c9STaylor Simpson## R GPR register 182793958c9STaylor Simpson## M modifier register 183144da357STaylor Simpson## Q HVX predicate vector 184144da357STaylor Simpson## V HVX vector register 185144da357STaylor Simpson## O HVX new vector register 186793958c9STaylor Simpson## regid can be one of the following 187793958c9STaylor Simpson## d, e destination register 188793958c9STaylor Simpson## dd destination register pair 189793958c9STaylor Simpson## s, t, u, v, w source register 190793958c9STaylor Simpson## ss, tt, uu, vv source register pair 191793958c9STaylor Simpson## x, y read-write register 192793958c9STaylor Simpson## xx, yy read-write register pair 193793958c9STaylor Simpson## 194793958c9STaylor Simpsondef get_tagregs(): 195793958c9STaylor Simpson return dict(zip(tags, list(map(compute_tag_regs, tags)))) 196793958c9STaylor Simpson 1975bb322e2SMarco Liebel 198793958c9STaylor Simpsondef get_tagimms(): 199793958c9STaylor Simpson return dict(zip(tags, list(map(compute_tag_immediates, tags)))) 200793958c9STaylor Simpson 2015bb322e2SMarco Liebel 202793958c9STaylor Simpsondef is_pair(regid): 203793958c9STaylor Simpson return len(regid) == 2 204793958c9STaylor Simpson 2055bb322e2SMarco Liebel 206793958c9STaylor Simpsondef is_single(regid): 207793958c9STaylor Simpson return len(regid) == 1 208793958c9STaylor Simpson 2095bb322e2SMarco Liebel 210793958c9STaylor Simpsondef is_written(regid): 211793958c9STaylor Simpson return regid[0] in "dexy" 212793958c9STaylor Simpson 2135bb322e2SMarco Liebel 214793958c9STaylor Simpsondef is_writeonly(regid): 215793958c9STaylor Simpson return regid[0] in "de" 216793958c9STaylor Simpson 2175bb322e2SMarco Liebel 218793958c9STaylor Simpsondef is_read(regid): 219793958c9STaylor Simpson return regid[0] in "stuvwxy" 220793958c9STaylor Simpson 2215bb322e2SMarco Liebel 222793958c9STaylor Simpsondef is_readwrite(regid): 223793958c9STaylor Simpson return regid[0] in "xy" 224793958c9STaylor Simpson 2255bb322e2SMarco Liebel 226793958c9STaylor Simpsondef is_scalar_reg(regtype): 227793958c9STaylor Simpson return regtype in "RPC" 228793958c9STaylor Simpson 2295bb322e2SMarco Liebel 230144da357STaylor Simpsondef is_hvx_reg(regtype): 231144da357STaylor Simpson return regtype in "VQ" 232144da357STaylor Simpson 2335bb322e2SMarco Liebel 234793958c9STaylor Simpsondef is_old_val(regtype, regid, tag): 2355bb322e2SMarco Liebel return regtype + regid + "V" in semdict[tag] 2365bb322e2SMarco Liebel 237793958c9STaylor Simpson 238793958c9STaylor Simpsondef is_new_val(regtype, regid, tag): 2395bb322e2SMarco Liebel return regtype + regid + "N" in semdict[tag] 2405bb322e2SMarco Liebel 241793958c9STaylor Simpson 242793958c9STaylor Simpsondef need_slot(tag): 2435bb322e2SMarco Liebel if ( 2445bb322e2SMarco Liebel ("A_CONDEXEC" in attribdict[tag] and "A_JUMP" not in attribdict[tag]) 2455bb322e2SMarco Liebel or "A_STORE" in attribdict[tag] 2465bb322e2SMarco Liebel or "A_LOAD" in attribdict[tag] 2475bb322e2SMarco Liebel ): 248793958c9STaylor Simpson return 1 249793958c9STaylor Simpson else: 250793958c9STaylor Simpson return 0 251793958c9STaylor Simpson 2525bb322e2SMarco Liebel 253793958c9STaylor Simpsondef need_part1(tag): 254793958c9STaylor Simpson return re.compile(r"fPART1").search(semdict[tag]) 255793958c9STaylor Simpson 2565bb322e2SMarco Liebel 257793958c9STaylor Simpsondef need_ea(tag): 258793958c9STaylor Simpson return re.compile(r"\bEA\b").search(semdict[tag]) 259793958c9STaylor Simpson 2605bb322e2SMarco Liebel 26140085901STaylor Simpsondef need_PC(tag): 2625bb322e2SMarco Liebel return "A_IMPLICIT_READS_PC" in attribdict[tag] 2635bb322e2SMarco Liebel 26440085901STaylor Simpson 265613653e5STaylor Simpsondef helper_needs_next_PC(tag): 2665bb322e2SMarco Liebel return "A_CALL" in attribdict[tag] 2675bb322e2SMarco Liebel 268613653e5STaylor Simpson 269fb67c2bfSTaylor Simpsondef need_pkt_has_multi_cof(tag): 2705bb322e2SMarco Liebel return "A_COF" in attribdict[tag] 2715bb322e2SMarco Liebel 272fb67c2bfSTaylor Simpson 273e28b77a6STaylor Simpsondef need_condexec_reg(tag, regs): 2745bb322e2SMarco Liebel if "A_CONDEXEC" in attribdict[tag]: 275e28b77a6STaylor Simpson for regtype, regid, toss, numregs in regs: 276e28b77a6STaylor Simpson if is_writeonly(regid) and not is_hvx_reg(regtype): 277e28b77a6STaylor Simpson return True 278e28b77a6STaylor Simpson return False 279e28b77a6STaylor Simpson 2805bb322e2SMarco Liebel 281793958c9STaylor Simpsondef skip_qemu_helper(tag): 282793958c9STaylor Simpson return tag in overrides.keys() 283793958c9STaylor Simpson 2845bb322e2SMarco Liebel 285144da357STaylor Simpsondef is_tmp_result(tag): 2865bb322e2SMarco Liebel return "A_CVI_TMP" in attribdict[tag] or "A_CVI_TMP_DST" in attribdict[tag] 2875bb322e2SMarco Liebel 288144da357STaylor Simpson 289144da357STaylor Simpsondef is_new_result(tag): 2905bb322e2SMarco Liebel return "A_CVI_NEW" in attribdict[tag] 2915bb322e2SMarco Liebel 292144da357STaylor Simpson 293e71fdc4fSAlessandro Di Federicodef is_idef_parser_enabled(tag): 294e71fdc4fSAlessandro Di Federico return tag in idef_parser_enabled 295e71fdc4fSAlessandro Di Federico 2965bb322e2SMarco Liebel 297793958c9STaylor Simpsondef imm_name(immlett): 298cd6c4edfSMarco Liebel return f"{immlett}iV" 299793958c9STaylor Simpson 3005bb322e2SMarco Liebel 301793958c9STaylor Simpsondef read_semantics_file(name): 302793958c9STaylor Simpson eval_line = "" 3035bb322e2SMarco Liebel for line in open(name, "rt").readlines(): 304793958c9STaylor Simpson if not line.startswith("#"): 305793958c9STaylor Simpson eval_line += line 306793958c9STaylor Simpson if line.endswith("\\\n"): 307793958c9STaylor Simpson eval_line.rstrip("\\\n") 308793958c9STaylor Simpson else: 309793958c9STaylor Simpson eval(eval_line.strip()) 310793958c9STaylor Simpson eval_line = "" 311793958c9STaylor Simpson 3125bb322e2SMarco Liebel 313793958c9STaylor Simpsondef read_attribs_file(name): 3145bb322e2SMarco Liebel attribre = re.compile( 3155bb322e2SMarco Liebel r"DEF_ATTRIB\(([A-Za-z0-9_]+), ([^,]*), " 3165bb322e2SMarco Liebel + r'"([A-Za-z0-9_\.]*)", "([A-Za-z0-9_\.]*)"\)' 3175bb322e2SMarco Liebel ) 3185bb322e2SMarco Liebel for line in open(name, "rt").readlines(): 319793958c9STaylor Simpson if not attribre.match(line): 320793958c9STaylor Simpson continue 321793958c9STaylor Simpson (attrib_base, descr, rreg, wreg) = attribre.findall(line)[0] 3225bb322e2SMarco Liebel attrib_base = "A_" + attrib_base 3235bb322e2SMarco Liebel attribinfo[attrib_base] = {"rreg": rreg, "wreg": wreg, "descr": descr} 3245bb322e2SMarco Liebel 325793958c9STaylor Simpson 326793958c9STaylor Simpsondef read_overrides_file(name): 327793958c9STaylor Simpson overridere = re.compile("#define fGEN_TCG_([A-Za-z0-9_]+)\(.*") 3285bb322e2SMarco Liebel for line in open(name, "rt").readlines(): 329793958c9STaylor Simpson if not overridere.match(line): 330793958c9STaylor Simpson continue 331793958c9STaylor Simpson tag = overridere.findall(line)[0] 332793958c9STaylor Simpson overrides[tag] = True 333e71fdc4fSAlessandro Di Federico 3345bb322e2SMarco Liebel 335e71fdc4fSAlessandro Di Federicodef read_idef_parser_enabled_file(name): 336e71fdc4fSAlessandro Di Federico global idef_parser_enabled 337e71fdc4fSAlessandro Di Federico with open(name, "r") as idef_parser_enabled_file: 338e71fdc4fSAlessandro Di Federico lines = idef_parser_enabled_file.read().strip().split("\n") 339e71fdc4fSAlessandro Di Federico idef_parser_enabled = set(lines) 340