1#!/usr/bin/env python3
2
3##
4##  Copyright(c) 2019-2021 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_slot(tag):
242            if i > 0: f.write(", ")
243            f.write("uint32_t slot")
244            i += 1
245        if hex_common.need_part1(tag):
246            if i > 0: f.write(", ")
247            f.write("uint32_t part1")
248        f.write(")\n{\n")
249        if (not hex_common.need_slot(tag)):
250            f.write("    uint32_t slot __attribute__((unused)) = 4;\n" )
251        if hex_common.need_ea(tag): gen_decl_ea(f)
252        ## Declare the return variable
253        i=0
254        for regtype,regid,toss,numregs in regs:
255            if (hex_common.is_writeonly(regid)):
256                gen_helper_dest_decl_opn(f,regtype,regid,i)
257            i += 1
258
259        for regtype,regid,toss,numregs in regs:
260            if (hex_common.is_read(regid)):
261                if (hex_common.is_pair(regid)):
262                    if (hex_common.is_hvx_reg(regtype)):
263                        gen_helper_src_var_ext_pair(f,regtype,regid,i)
264                elif (hex_common.is_single(regid)):
265                    if (hex_common.is_hvx_reg(regtype)):
266                        gen_helper_src_var_ext(f,regtype,regid)
267                else:
268                    print("Bad register parse: ",regtype,regid,toss,numregs)
269
270        if 'A_FPOP' in hex_common.attribdict[tag]:
271            f.write('    arch_fpop_start(env);\n');
272
273        f.write("    %s\n" % hex_common.semdict[tag])
274
275        if 'A_FPOP' in hex_common.attribdict[tag]:
276            f.write('    arch_fpop_end(env);\n');
277
278        ## Save/return the return variable
279        for regtype,regid,toss,numregs in regs:
280            if (hex_common.is_written(regid)):
281                gen_helper_return_opn(f, regtype, regid, i)
282        f.write("}\n\n")
283        ## End of the helper definition
284
285def main():
286    hex_common.read_semantics_file(sys.argv[1])
287    hex_common.read_attribs_file(sys.argv[2])
288    hex_common.read_overrides_file(sys.argv[3])
289    hex_common.read_overrides_file(sys.argv[4])
290    hex_common.calculate_attribs()
291    tagregs = hex_common.get_tagregs()
292    tagimms = hex_common.get_tagimms()
293
294    with open(sys.argv[5], 'w') as f:
295        for tag in hex_common.tags:
296            ## Skip the priv instructions
297            if ( "A_PRIV" in hex_common.attribdict[tag] ) :
298                continue
299            ## Skip the guest instructions
300            if ( "A_GUEST" in hex_common.attribdict[tag] ) :
301                continue
302            ## Skip the diag instructions
303            if ( tag == "Y6_diag" ) :
304                continue
305            if ( tag == "Y6_diag0" ) :
306                continue
307            if ( tag == "Y6_diag1" ) :
308                continue
309            if ( hex_common.skip_qemu_helper(tag) ):
310                continue
311
312            gen_helper_function(f, tag, tagregs, tagimms)
313
314if __name__ == "__main__":
315    main()
316