xref: /qemu/target/hexagon/gen_helper_funcs.py (revision 29b62a10)
1#!/usr/bin/env python3
2
3##
4##  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved.
5##
6##  This program is free software; you can redistribute it and/or modify
7##  it under the terms of the GNU General Public License as published by
8##  the Free Software Foundation; either version 2 of the License, or
9##  (at your option) any later version.
10##
11##  This program is distributed in the hope that it will be useful,
12##  but WITHOUT ANY WARRANTY; without even the implied warranty of
13##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14##  GNU General Public License for more details.
15##
16##  You should have received a copy of the GNU General Public License
17##  along with this program; if not, see <http://www.gnu.org/licenses/>.
18##
19
20import sys
21import re
22import string
23import hex_common
24
25##
26## Helpers for gen_helper_function
27##
28def gen_decl_ea(f):
29    f.write("    uint32_t EA;\n")
30
31def gen_helper_return_type(f,regtype,regid,regno):
32    if regno > 1 : f.write(", ")
33    f.write("int32_t")
34
35def gen_helper_return_type_pair(f,regtype,regid,regno):
36    if regno > 1 : f.write(", ")
37    f.write("int64_t")
38
39def gen_helper_arg(f,regtype,regid,regno):
40    if regno > 0 : f.write(", " )
41    f.write("int32_t %s%sV" % (regtype,regid))
42
43def gen_helper_arg_new(f,regtype,regid,regno):
44    if regno >= 0 : f.write(", " )
45    f.write("int32_t %s%sN" % (regtype,regid))
46
47def gen_helper_arg_pair(f,regtype,regid,regno):
48    if regno >= 0 : f.write(", ")
49    f.write("int64_t %s%sV" % (regtype,regid))
50
51def gen_helper_arg_ext(f,regtype,regid,regno):
52    if regno > 0 : f.write(", ")
53    f.write("void *%s%sV_void" % (regtype,regid))
54
55def gen_helper_arg_ext_pair(f,regtype,regid,regno):
56    if regno > 0 : f.write(", ")
57    f.write("void *%s%sV_void" % (regtype,regid))
58
59def gen_helper_arg_opn(f,regtype,regid,i,tag):
60    if (hex_common.is_pair(regid)):
61        if (hex_common.is_hvx_reg(regtype)):
62            gen_helper_arg_ext_pair(f,regtype,regid,i)
63        else:
64            gen_helper_arg_pair(f,regtype,regid,i)
65    elif (hex_common.is_single(regid)):
66        if hex_common.is_old_val(regtype, regid, tag):
67            if (hex_common.is_hvx_reg(regtype)):
68                gen_helper_arg_ext(f,regtype,regid,i)
69            else:
70                gen_helper_arg(f,regtype,regid,i)
71        elif hex_common.is_new_val(regtype, regid, tag):
72            gen_helper_arg_new(f,regtype,regid,i)
73        else:
74            print("Bad register parse: ",regtype,regid,toss,numregs)
75    else:
76        print("Bad register parse: ",regtype,regid,toss,numregs)
77
78def gen_helper_arg_imm(f,immlett):
79    f.write(", int32_t %s" % (hex_common.imm_name(immlett)))
80
81def gen_helper_dest_decl(f,regtype,regid,regno,subfield=""):
82    f.write("    int32_t %s%sV%s = 0;\n" % \
83        (regtype,regid,subfield))
84
85def gen_helper_dest_decl_pair(f,regtype,regid,regno,subfield=""):
86    f.write("    int64_t %s%sV%s = 0;\n" % \
87        (regtype,regid,subfield))
88
89def gen_helper_dest_decl_ext(f,regtype,regid):
90    if (regtype == "Q"):
91        f.write("    /* %s%sV is *(MMQReg *)(%s%sV_void) */\n" % \
92            (regtype,regid,regtype,regid))
93    else:
94        f.write("    /* %s%sV is *(MMVector *)(%s%sV_void) */\n" % \
95            (regtype,regid,regtype,regid))
96
97def gen_helper_dest_decl_ext_pair(f,regtype,regid,regno):
98    f.write("    /* %s%sV is *(MMVectorPair *))%s%sV_void) */\n" % \
99        (regtype,regid,regtype, regid))
100
101def gen_helper_dest_decl_opn(f,regtype,regid,i):
102    if (hex_common.is_pair(regid)):
103        if (hex_common.is_hvx_reg(regtype)):
104            gen_helper_dest_decl_ext_pair(f,regtype,regid, i)
105        else:
106            gen_helper_dest_decl_pair(f,regtype,regid,i)
107    elif (hex_common.is_single(regid)):
108        if (hex_common.is_hvx_reg(regtype)):
109            gen_helper_dest_decl_ext(f,regtype,regid)
110        else:
111            gen_helper_dest_decl(f,regtype,regid,i)
112    else:
113        print("Bad register parse: ",regtype,regid,toss,numregs)
114
115def gen_helper_src_var_ext(f,regtype,regid):
116    if (regtype == "Q"):
117       f.write("    /* %s%sV is *(MMQReg *)(%s%sV_void) */\n" % \
118           (regtype,regid,regtype,regid))
119    else:
120       f.write("    /* %s%sV is *(MMVector *)(%s%sV_void) */\n" % \
121           (regtype,regid,regtype,regid))
122
123def gen_helper_src_var_ext_pair(f,regtype,regid,regno):
124    f.write("    /* %s%sV%s is *(MMVectorPair *)(%s%sV%s_void) */\n" % \
125        (regtype,regid,regno,regtype,regid,regno))
126
127def gen_helper_return(f,regtype,regid,regno):
128    f.write("    return %s%sV;\n" % (regtype,regid))
129
130def gen_helper_return_pair(f,regtype,regid,regno):
131    f.write("    return %s%sV;\n" % (regtype,regid))
132
133def gen_helper_dst_write_ext(f,regtype,regid):
134    return
135
136def gen_helper_dst_write_ext_pair(f,regtype,regid):
137    return
138
139def gen_helper_return_opn(f, regtype, regid, i):
140    if (hex_common.is_pair(regid)):
141        if (hex_common.is_hvx_reg(regtype)):
142            gen_helper_dst_write_ext_pair(f,regtype,regid)
143        else:
144            gen_helper_return_pair(f,regtype,regid,i)
145    elif (hex_common.is_single(regid)):
146        if (hex_common.is_hvx_reg(regtype)):
147            gen_helper_dst_write_ext(f,regtype,regid)
148        else:
149            gen_helper_return(f,regtype,regid,i)
150    else:
151        print("Bad register parse: ",regtype,regid,toss,numregs)
152
153##
154## Generate the TCG code to call the helper
155##     For A2_add: Rd32=add(Rs32,Rt32), { RdV=RsV+RtV;}
156##     We produce:
157##       int32_t HELPER(A2_add)(CPUHexagonState *env, int32_t RsV, int32_t RtV)
158##       {
159##           uint32_t slot __attribute__(unused)) = 4;
160##           int32_t RdV = 0;
161##           { RdV=RsV+RtV;}
162##           COUNT_HELPER(A2_add);
163##           return RdV;
164##       }
165##
166def gen_helper_function(f, tag, tagregs, tagimms):
167    regs = tagregs[tag]
168    imms = tagimms[tag]
169
170    numresults = 0
171    numscalarresults = 0
172    numscalarreadwrite = 0
173    for regtype,regid,toss,numregs in regs:
174        if (hex_common.is_written(regid)):
175            numresults += 1
176            if (hex_common.is_scalar_reg(regtype)):
177                numscalarresults += 1
178        if (hex_common.is_readwrite(regid)):
179            if (hex_common.is_scalar_reg(regtype)):
180                numscalarreadwrite += 1
181
182    if (numscalarresults > 1):
183        ## The helper is bogus when there is more than one result
184        f.write("void HELPER(%s)(CPUHexagonState *env) { BOGUS_HELPER(%s); }\n"
185                % (tag, tag))
186    else:
187        ## The return type of the function is the type of the destination
188        ## register (if scalar)
189        i=0
190        for regtype,regid,toss,numregs in regs:
191            if (hex_common.is_written(regid)):
192                if (hex_common.is_pair(regid)):
193                    if (hex_common.is_hvx_reg(regtype)):
194                        continue
195                    else:
196                        gen_helper_return_type_pair(f,regtype,regid,i)
197                elif (hex_common.is_single(regid)):
198                    if (hex_common.is_hvx_reg(regtype)):
199                            continue
200                    else:
201                        gen_helper_return_type(f,regtype,regid,i)
202                else:
203                    print("Bad register parse: ",regtype,regid,toss,numregs)
204            i += 1
205
206        if (numscalarresults == 0):
207            f.write("void")
208        f.write(" HELPER(%s)(CPUHexagonState *env" % tag)
209
210        ## Arguments include the vector destination operands
211        i = 1
212        for regtype,regid,toss,numregs in regs:
213            if (hex_common.is_written(regid)):
214                if (hex_common.is_pair(regid)):
215                    if (hex_common.is_hvx_reg(regtype)):
216                        gen_helper_arg_ext_pair(f,regtype,regid,i)
217                    else:
218                        continue
219                elif (hex_common.is_single(regid)):
220                    if (hex_common.is_hvx_reg(regtype)):
221                        gen_helper_arg_ext(f,regtype,regid,i)
222                    else:
223                        # This is the return value of the function
224                        continue
225                else:
226                    print("Bad register parse: ",regtype,regid,toss,numregs)
227                i += 1
228
229        ## Arguments to the helper function are the source regs and immediates
230        for regtype,regid,toss,numregs in regs:
231            if (hex_common.is_read(regid)):
232                if (hex_common.is_hvx_reg(regtype) and
233                    hex_common.is_readwrite(regid)):
234                    continue
235                gen_helper_arg_opn(f,regtype,regid,i,tag)
236                i += 1
237        for immlett,bits,immshift in imms:
238            gen_helper_arg_imm(f,immlett)
239            i += 1
240
241        if (hex_common.need_pkt_has_multi_cof(tag)):
242            f.write(", uint32_t pkt_has_multi_cof")
243
244        if hex_common.need_PC(tag):
245            if i > 0: f.write(", ")
246            f.write("target_ulong PC")
247            i += 1
248        if hex_common.helper_needs_next_PC(tag):
249            if i > 0: f.write(", ")
250            f.write("target_ulong next_PC")
251            i += 1
252        if hex_common.need_slot(tag):
253            if i > 0: f.write(", ")
254            f.write("uint32_t slot")
255            i += 1
256        if hex_common.need_part1(tag):
257            if i > 0: f.write(", ")
258            f.write("uint32_t part1")
259        f.write(")\n{\n")
260        if (not hex_common.need_slot(tag)):
261            f.write("    uint32_t slot __attribute__((unused)) = 4;\n" )
262        if hex_common.need_ea(tag): gen_decl_ea(f)
263        ## Declare the return variable
264        i=0
265        for regtype,regid,toss,numregs in regs:
266            if (hex_common.is_writeonly(regid)):
267                gen_helper_dest_decl_opn(f,regtype,regid,i)
268            i += 1
269
270        for regtype,regid,toss,numregs in regs:
271            if (hex_common.is_read(regid)):
272                if (hex_common.is_pair(regid)):
273                    if (hex_common.is_hvx_reg(regtype)):
274                        gen_helper_src_var_ext_pair(f,regtype,regid,i)
275                elif (hex_common.is_single(regid)):
276                    if (hex_common.is_hvx_reg(regtype)):
277                        gen_helper_src_var_ext(f,regtype,regid)
278                else:
279                    print("Bad register parse: ",regtype,regid,toss,numregs)
280
281        if 'A_FPOP' in hex_common.attribdict[tag]:
282            f.write('    arch_fpop_start(env);\n');
283
284        f.write("    %s\n" % hex_common.semdict[tag])
285
286        if 'A_FPOP' in hex_common.attribdict[tag]:
287            f.write('    arch_fpop_end(env);\n');
288
289        ## Save/return the return variable
290        for regtype,regid,toss,numregs in regs:
291            if (hex_common.is_written(regid)):
292                gen_helper_return_opn(f, regtype, regid, i)
293        f.write("}\n\n")
294        ## End of the helper definition
295
296def main():
297    hex_common.read_semantics_file(sys.argv[1])
298    hex_common.read_attribs_file(sys.argv[2])
299    hex_common.read_overrides_file(sys.argv[3])
300    hex_common.read_overrides_file(sys.argv[4])
301    ## Whether or not idef-parser is enabled is
302    ## determined by the number of arguments to
303    ## this script:
304    ##
305    ##   5 args. -> not enabled,
306    ##   6 args. -> idef-parser enabled.
307    ##
308    ## The 6:th arg. then holds a list of the successfully
309    ## parsed instructions.
310    is_idef_parser_enabled = len(sys.argv) > 6
311    if is_idef_parser_enabled:
312        hex_common.read_idef_parser_enabled_file(sys.argv[5])
313    hex_common.calculate_attribs()
314    tagregs = hex_common.get_tagregs()
315    tagimms = hex_common.get_tagimms()
316
317    output_file = sys.argv[-1]
318    with open(output_file, 'w') as f:
319        for tag in hex_common.tags:
320            ## Skip the priv instructions
321            if ( "A_PRIV" in hex_common.attribdict[tag] ) :
322                continue
323            ## Skip the guest instructions
324            if ( "A_GUEST" in hex_common.attribdict[tag] ) :
325                continue
326            ## Skip the diag instructions
327            if ( tag == "Y6_diag" ) :
328                continue
329            if ( tag == "Y6_diag0" ) :
330                continue
331            if ( tag == "Y6_diag1" ) :
332                continue
333            if ( hex_common.skip_qemu_helper(tag) ):
334                continue
335            if ( hex_common.is_idef_parser_enabled(tag) ):
336                continue
337
338            gen_helper_function(f, tag, tagregs, tagimms)
339
340if __name__ == "__main__":
341    main()
342