xref: /qemu/target/hexagon/gen_helper_protos.py (revision 5bb322e2)
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 Simpsonimport hex_common
24793958c9STaylor Simpson
25793958c9STaylor Simpson##
26793958c9STaylor Simpson## Helpers for gen_helper_prototype
27793958c9STaylor Simpson##
28793958c9STaylor Simpsondef_helper_types = {
295bb322e2SMarco Liebel    "N": "s32",
305bb322e2SMarco Liebel    "O": "s32",
315bb322e2SMarco Liebel    "P": "s32",
325bb322e2SMarco Liebel    "M": "s32",
335bb322e2SMarco Liebel    "C": "s32",
345bb322e2SMarco Liebel    "R": "s32",
355bb322e2SMarco Liebel    "V": "ptr",
365bb322e2SMarco Liebel    "Q": "ptr",
37793958c9STaylor Simpson}
38793958c9STaylor Simpson
39793958c9STaylor Simpsondef_helper_types_pair = {
405bb322e2SMarco Liebel    "R": "s64",
415bb322e2SMarco Liebel    "C": "s64",
425bb322e2SMarco Liebel    "S": "s64",
435bb322e2SMarco Liebel    "G": "s64",
445bb322e2SMarco Liebel    "V": "ptr",
455bb322e2SMarco Liebel    "Q": "ptr",
46793958c9STaylor Simpson}
47793958c9STaylor Simpson
485bb322e2SMarco Liebel
49793958c9STaylor Simpsondef gen_def_helper_opn(f, tag, regtype, regid, toss, numregs, i):
505bb322e2SMarco Liebel    if hex_common.is_pair(regid):
51cd6c4edfSMarco Liebel        f.write(f", {def_helper_types_pair[regtype]}")
525bb322e2SMarco Liebel    elif hex_common.is_single(regid):
53cd6c4edfSMarco Liebel        f.write(f", {def_helper_types[regtype]}")
54793958c9STaylor Simpson    else:
55793958c9STaylor Simpson        print("Bad register parse: ", regtype, regid, toss, numregs)
56793958c9STaylor Simpson
575bb322e2SMarco Liebel
58793958c9STaylor Simpson##
59793958c9STaylor Simpson## Generate the DEF_HELPER prototype for an instruction
60793958c9STaylor Simpson##     For A2_add: Rd32=add(Rs32,Rt32)
61793958c9STaylor Simpson##     We produce:
62793958c9STaylor Simpson##         DEF_HELPER_3(A2_add, s32, env, s32, s32)
63793958c9STaylor Simpson##
64793958c9STaylor Simpsondef gen_helper_prototype(f, tag, tagregs, tagimms):
65793958c9STaylor Simpson    regs = tagregs[tag]
66793958c9STaylor Simpson    imms = tagimms[tag]
67793958c9STaylor Simpson
68793958c9STaylor Simpson    numresults = 0
69793958c9STaylor Simpson    numscalarresults = 0
70793958c9STaylor Simpson    numscalarreadwrite = 0
71793958c9STaylor Simpson    for regtype, regid, toss, numregs in regs:
725bb322e2SMarco Liebel        if hex_common.is_written(regid):
73793958c9STaylor Simpson            numresults += 1
745bb322e2SMarco Liebel            if hex_common.is_scalar_reg(regtype):
75793958c9STaylor Simpson                numscalarresults += 1
765bb322e2SMarco Liebel        if hex_common.is_readwrite(regid):
775bb322e2SMarco Liebel            if hex_common.is_scalar_reg(regtype):
78793958c9STaylor Simpson                numscalarreadwrite += 1
79793958c9STaylor Simpson
805bb322e2SMarco Liebel    if numscalarresults > 1:
81793958c9STaylor Simpson        ## The helper is bogus when there is more than one result
825bb322e2SMarco Liebel        f.write(f"DEF_HELPER_1({tag}, void, env)\n")
83793958c9STaylor Simpson    else:
84793958c9STaylor Simpson        ## Figure out how many arguments the helper will take
855bb322e2SMarco Liebel        if numscalarresults == 0:
86793958c9STaylor Simpson            def_helper_size = len(regs) + len(imms) + numscalarreadwrite + 1
875bb322e2SMarco Liebel            if hex_common.need_pkt_has_multi_cof(tag):
885bb322e2SMarco Liebel                def_helper_size += 1
895bb322e2SMarco Liebel            if hex_common.need_part1(tag):
905bb322e2SMarco Liebel                def_helper_size += 1
915bb322e2SMarco Liebel            if hex_common.need_slot(tag):
925bb322e2SMarco Liebel                def_helper_size += 1
935bb322e2SMarco Liebel            if hex_common.need_PC(tag):
945bb322e2SMarco Liebel                def_helper_size += 1
955bb322e2SMarco Liebel            if hex_common.helper_needs_next_PC(tag):
965bb322e2SMarco Liebel                def_helper_size += 1
975bb322e2SMarco Liebel            if hex_common.need_condexec_reg(tag, regs):
985bb322e2SMarco Liebel                def_helper_size += 1
995bb322e2SMarco Liebel            f.write(f"DEF_HELPER_{def_helper_size}({tag}")
100793958c9STaylor Simpson            ## The return type is void
1015bb322e2SMarco Liebel            f.write(", void")
102793958c9STaylor Simpson        else:
103793958c9STaylor Simpson            def_helper_size = len(regs) + len(imms) + numscalarreadwrite
1045bb322e2SMarco Liebel            if hex_common.need_pkt_has_multi_cof(tag):
1055bb322e2SMarco Liebel                def_helper_size += 1
1065bb322e2SMarco Liebel            if hex_common.need_part1(tag):
1075bb322e2SMarco Liebel                def_helper_size += 1
1085bb322e2SMarco Liebel            if hex_common.need_slot(tag):
1095bb322e2SMarco Liebel                def_helper_size += 1
1105bb322e2SMarco Liebel            if hex_common.need_PC(tag):
1115bb322e2SMarco Liebel                def_helper_size += 1
1125bb322e2SMarco Liebel            if hex_common.need_condexec_reg(tag, regs):
1135bb322e2SMarco Liebel                def_helper_size += 1
1145bb322e2SMarco Liebel            if hex_common.helper_needs_next_PC(tag):
1155bb322e2SMarco Liebel                def_helper_size += 1
1165bb322e2SMarco Liebel            f.write(f"DEF_HELPER_{def_helper_size}({tag}")
117793958c9STaylor Simpson
118793958c9STaylor Simpson        ## Generate the qemu DEF_HELPER type for each result
119ccd9eec8STaylor Simpson        ## Iterate over this list twice
120ccd9eec8STaylor Simpson        ## - Emit the scalar result
121ccd9eec8STaylor Simpson        ## - Emit the vector result
122793958c9STaylor Simpson        i = 0
123793958c9STaylor Simpson        for regtype, regid, toss, numregs in regs:
1245bb322e2SMarco Liebel            if hex_common.is_written(regid):
1255bb322e2SMarco Liebel                if not hex_common.is_hvx_reg(regtype):
126793958c9STaylor Simpson                    gen_def_helper_opn(f, tag, regtype, regid, toss, numregs, i)
127793958c9STaylor Simpson                i += 1
128793958c9STaylor Simpson
129793958c9STaylor Simpson        ## Put the env between the outputs and inputs
1305bb322e2SMarco Liebel        f.write(", env")
131793958c9STaylor Simpson        i += 1
132793958c9STaylor Simpson
133ccd9eec8STaylor Simpson        # Second pass
134ccd9eec8STaylor Simpson        for regtype, regid, toss, numregs in regs:
1355bb322e2SMarco Liebel            if hex_common.is_written(regid):
1365bb322e2SMarco Liebel                if hex_common.is_hvx_reg(regtype):
137ccd9eec8STaylor Simpson                    gen_def_helper_opn(f, tag, regtype, regid, toss, numregs, i)
138ccd9eec8STaylor Simpson                    i += 1
139ccd9eec8STaylor Simpson
140e28b77a6STaylor Simpson        ## For conditional instructions, we pass in the destination register
1415bb322e2SMarco Liebel        if "A_CONDEXEC" in hex_common.attribdict[tag]:
142e28b77a6STaylor Simpson            for regtype, regid, toss, numregs in regs:
1435bb322e2SMarco Liebel                if hex_common.is_writeonly(regid) and not hex_common.is_hvx_reg(
1445bb322e2SMarco Liebel                    regtype
1455bb322e2SMarco Liebel                ):
146e28b77a6STaylor Simpson                    gen_def_helper_opn(f, tag, regtype, regid, toss, numregs, i)
147e28b77a6STaylor Simpson                    i += 1
148e28b77a6STaylor Simpson
149793958c9STaylor Simpson        ## Generate the qemu type for each input operand (regs and immediates)
150793958c9STaylor Simpson        for regtype, regid, toss, numregs in regs:
1515bb322e2SMarco Liebel            if hex_common.is_read(regid):
1525bb322e2SMarco Liebel                if hex_common.is_hvx_reg(regtype) and hex_common.is_readwrite(regid):
153ccd9eec8STaylor Simpson                    continue
154793958c9STaylor Simpson                gen_def_helper_opn(f, tag, regtype, regid, toss, numregs, i)
155793958c9STaylor Simpson                i += 1
156793958c9STaylor Simpson        for immlett, bits, immshift in imms:
157793958c9STaylor Simpson            f.write(", s32")
158793958c9STaylor Simpson
159fb67c2bfSTaylor Simpson        ## Add the arguments for the instruction pkt_has_multi_cof, slot and
160fb67c2bfSTaylor Simpson        ## part1 (if needed)
1615bb322e2SMarco Liebel        if hex_common.need_pkt_has_multi_cof(tag):
1625bb322e2SMarco Liebel            f.write(", i32")
1635bb322e2SMarco Liebel        if hex_common.need_PC(tag):
1645bb322e2SMarco Liebel            f.write(", i32")
1655bb322e2SMarco Liebel        if hex_common.helper_needs_next_PC(tag):
1665bb322e2SMarco Liebel            f.write(", i32")
1675bb322e2SMarco Liebel        if hex_common.need_slot(tag):
1685bb322e2SMarco Liebel            f.write(", i32")
1695bb322e2SMarco Liebel        if hex_common.need_part1(tag):
1705bb322e2SMarco Liebel            f.write(" , i32")
1715bb322e2SMarco Liebel        f.write(")\n")
1725bb322e2SMarco Liebel
173793958c9STaylor Simpson
174793958c9STaylor Simpsondef main():
175793958c9STaylor Simpson    hex_common.read_semantics_file(sys.argv[1])
176793958c9STaylor Simpson    hex_common.read_attribs_file(sys.argv[2])
177793958c9STaylor Simpson    hex_common.read_overrides_file(sys.argv[3])
178d51bcabeSTaylor Simpson    hex_common.read_overrides_file(sys.argv[4])
179e71fdc4fSAlessandro Di Federico    ## Whether or not idef-parser is enabled is
180e71fdc4fSAlessandro Di Federico    ## determined by the number of arguments to
181e71fdc4fSAlessandro Di Federico    ## this script:
182e71fdc4fSAlessandro Di Federico    ##
183e71fdc4fSAlessandro Di Federico    ##   5 args. -> not enabled,
184e71fdc4fSAlessandro Di Federico    ##   6 args. -> idef-parser enabled.
185e71fdc4fSAlessandro Di Federico    ##
186e71fdc4fSAlessandro Di Federico    ## The 6:th arg. then holds a list of the successfully
187e71fdc4fSAlessandro Di Federico    ## parsed instructions.
188e71fdc4fSAlessandro Di Federico    is_idef_parser_enabled = len(sys.argv) > 6
189e71fdc4fSAlessandro Di Federico    if is_idef_parser_enabled:
190e71fdc4fSAlessandro Di Federico        hex_common.read_idef_parser_enabled_file(sys.argv[5])
191793958c9STaylor Simpson    hex_common.calculate_attribs()
192793958c9STaylor Simpson    tagregs = hex_common.get_tagregs()
193793958c9STaylor Simpson    tagimms = hex_common.get_tagimms()
194793958c9STaylor Simpson
195e71fdc4fSAlessandro Di Federico    output_file = sys.argv[-1]
1965bb322e2SMarco Liebel    with open(output_file, "w") as f:
197793958c9STaylor Simpson        for tag in hex_common.tags:
198793958c9STaylor Simpson            ## Skip the priv instructions
1995bb322e2SMarco Liebel            if "A_PRIV" in hex_common.attribdict[tag]:
200793958c9STaylor Simpson                continue
201793958c9STaylor Simpson            ## Skip the guest instructions
2025bb322e2SMarco Liebel            if "A_GUEST" in hex_common.attribdict[tag]:
203793958c9STaylor Simpson                continue
204793958c9STaylor Simpson            ## Skip the diag instructions
2055bb322e2SMarco Liebel            if tag == "Y6_diag":
206793958c9STaylor Simpson                continue
2075bb322e2SMarco Liebel            if tag == "Y6_diag0":
208793958c9STaylor Simpson                continue
2095bb322e2SMarco Liebel            if tag == "Y6_diag1":
210793958c9STaylor Simpson                continue
211793958c9STaylor Simpson
2125bb322e2SMarco Liebel            if hex_common.skip_qemu_helper(tag):
213793958c9STaylor Simpson                continue
2145bb322e2SMarco Liebel            if hex_common.is_idef_parser_enabled(tag):
215e71fdc4fSAlessandro Di Federico                continue
216793958c9STaylor Simpson
217793958c9STaylor Simpson            gen_helper_prototype(f, tag, tagregs, tagimms)
218793958c9STaylor Simpson
2195bb322e2SMarco Liebel
220793958c9STaylor Simpsonif __name__ == "__main__":
221793958c9STaylor Simpson    main()
222