xref: /qemu/target/hexagon/hex_common.py (revision e71fdc4f)
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