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_opn(f,regtype,regid,i,tag):
52    if (hex_common.is_pair(regid)):
53        gen_helper_arg_pair(f,regtype,regid,i)
54    elif (hex_common.is_single(regid)):
55        if hex_common.is_old_val(regtype, regid, tag):
56            gen_helper_arg(f,regtype,regid,i)
57        elif hex_common.is_new_val(regtype, regid, tag):
58            gen_helper_arg_new(f,regtype,regid,i)
59        else:
60            print("Bad register parse: ",regtype,regid,toss,numregs)
61    else:
62        print("Bad register parse: ",regtype,regid,toss,numregs)
63
64def gen_helper_arg_imm(f,immlett):
65    f.write(", int32_t %s" % (hex_common.imm_name(immlett)))
66
67def gen_helper_dest_decl(f,regtype,regid,regno,subfield=""):
68    f.write("    int32_t %s%sV%s = 0;\n" % \
69        (regtype,regid,subfield))
70
71def gen_helper_dest_decl_pair(f,regtype,regid,regno,subfield=""):
72    f.write("    int64_t %s%sV%s = 0;\n" % \
73        (regtype,regid,subfield))
74
75def gen_helper_dest_decl_opn(f,regtype,regid,i):
76    if (hex_common.is_pair(regid)):
77        gen_helper_dest_decl_pair(f,regtype,regid,i)
78    elif (hex_common.is_single(regid)):
79        gen_helper_dest_decl(f,regtype,regid,i)
80    else:
81        print("Bad register parse: ",regtype,regid,toss,numregs)
82
83def gen_helper_return(f,regtype,regid,regno):
84    f.write("    return %s%sV;\n" % (regtype,regid))
85
86def gen_helper_return_pair(f,regtype,regid,regno):
87    f.write("    return %s%sV;\n" % (regtype,regid))
88
89def gen_helper_return_opn(f, regtype, regid, i):
90    if (hex_common.is_pair(regid)):
91        gen_helper_return_pair(f,regtype,regid,i)
92    elif (hex_common.is_single(regid)):
93        gen_helper_return(f,regtype,regid,i)
94    else:
95        print("Bad register parse: ",regtype,regid,toss,numregs)
96
97##
98## Generate the TCG code to call the helper
99##     For A2_add: Rd32=add(Rs32,Rt32), { RdV=RsV+RtV;}
100##     We produce:
101##       int32_t HELPER(A2_add)(CPUHexagonState *env, int32_t RsV, int32_t RtV)
102##       {
103##           uint32_t slot __attribute__(unused)) = 4;
104##           int32_t RdV = 0;
105##           { RdV=RsV+RtV;}
106##           COUNT_HELPER(A2_add);
107##           return RdV;
108##       }
109##
110def gen_helper_function(f, tag, tagregs, tagimms):
111    regs = tagregs[tag]
112    imms = tagimms[tag]
113
114    numresults = 0
115    numscalarresults = 0
116    numscalarreadwrite = 0
117    for regtype,regid,toss,numregs in regs:
118        if (hex_common.is_written(regid)):
119            numresults += 1
120            if (hex_common.is_scalar_reg(regtype)):
121                numscalarresults += 1
122        if (hex_common.is_readwrite(regid)):
123            if (hex_common.is_scalar_reg(regtype)):
124                numscalarreadwrite += 1
125
126    if (numscalarresults > 1):
127        ## The helper is bogus when there is more than one result
128        f.write("void HELPER(%s)(CPUHexagonState *env) { BOGUS_HELPER(%s); }\n"
129                % (tag, tag))
130    else:
131        ## The return type of the function is the type of the destination
132        ## register
133        i=0
134        for regtype,regid,toss,numregs in regs:
135            if (hex_common.is_written(regid)):
136                if (hex_common.is_pair(regid)):
137                    gen_helper_return_type_pair(f,regtype,regid,i)
138                elif (hex_common.is_single(regid)):
139                    gen_helper_return_type(f,regtype,regid,i)
140                else:
141                    print("Bad register parse: ",regtype,regid,toss,numregs)
142            i += 1
143
144        if (numscalarresults == 0):
145            f.write("void")
146        f.write(" HELPER(%s)(CPUHexagonState *env" % tag)
147
148        i = 1
149
150        ## Arguments to the helper function are the source regs and immediates
151        for regtype,regid,toss,numregs in regs:
152            if (hex_common.is_read(regid)):
153                gen_helper_arg_opn(f,regtype,regid,i,tag)
154                i += 1
155        for immlett,bits,immshift in imms:
156            gen_helper_arg_imm(f,immlett)
157            i += 1
158        if hex_common.need_slot(tag):
159            if i > 0: f.write(", ")
160            f.write("uint32_t slot")
161            i += 1
162        if hex_common.need_part1(tag):
163            if i > 0: f.write(", ")
164            f.write("uint32_t part1")
165        f.write(")\n{\n")
166        if (not hex_common.need_slot(tag)):
167            f.write("    uint32_t slot __attribute__((unused)) = 4;\n" )
168        if hex_common.need_ea(tag): gen_decl_ea(f)
169        ## Declare the return variable
170        i=0
171        for regtype,regid,toss,numregs in regs:
172            if (hex_common.is_writeonly(regid)):
173                gen_helper_dest_decl_opn(f,regtype,regid,i)
174            i += 1
175
176        if 'A_FPOP' in hex_common.attribdict[tag]:
177            f.write('    arch_fpop_start(env);\n');
178
179        f.write("    %s\n" % hex_common.semdict[tag])
180
181        if 'A_FPOP' in hex_common.attribdict[tag]:
182            f.write('    arch_fpop_end(env);\n');
183
184        ## Save/return the return variable
185        for regtype,regid,toss,numregs in regs:
186            if (hex_common.is_written(regid)):
187                gen_helper_return_opn(f, regtype, regid, i)
188        f.write("}\n\n")
189        ## End of the helper definition
190
191def main():
192    hex_common.read_semantics_file(sys.argv[1])
193    hex_common.read_attribs_file(sys.argv[2])
194    hex_common.read_overrides_file(sys.argv[3])
195    hex_common.calculate_attribs()
196    tagregs = hex_common.get_tagregs()
197    tagimms = hex_common.get_tagimms()
198
199    with open(sys.argv[4], 'w') as f:
200        for tag in hex_common.tags:
201            ## Skip the priv instructions
202            if ( "A_PRIV" in hex_common.attribdict[tag] ) :
203                continue
204            ## Skip the guest instructions
205            if ( "A_GUEST" in hex_common.attribdict[tag] ) :
206                continue
207            ## Skip the diag instructions
208            if ( tag == "Y6_diag" ) :
209                continue
210            if ( tag == "Y6_diag0" ) :
211                continue
212            if ( tag == "Y6_diag1" ) :
213                continue
214            if ( hex_common.skip_qemu_helper(tag) ):
215                continue
216
217            gen_helper_function(f, tag, tagregs, tagimms)
218
219if __name__ == "__main__":
220    main()
221