xref: /qemu/target/hexagon/gen_tcg_funcs.py (revision c8e7fef1)
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_tcg_func
27##
28def gen_decl_ea_tcg(f, tag):
29    if ('A_CONDEXEC' in hex_common.attribdict[tag] or
30        'A_LOAD' in hex_common.attribdict[tag]):
31        f.write("    TCGv EA = tcg_temp_local_new();\n")
32    else:
33        f.write("    TCGv EA = tcg_temp_new();\n")
34
35def gen_free_ea_tcg(f):
36    f.write("    tcg_temp_free(EA);\n")
37
38def genptr_decl_pair_writable(f, tag, regtype, regid, regno):
39    regN="%s%sN" % (regtype,regid)
40    f.write("    TCGv_i64 %s%sV = tcg_temp_local_new_i64();\n" % \
41        (regtype, regid))
42    if (regtype == "C"):
43        f.write("    const int %s = insn->regno[%d] + HEX_REG_SA0;\n" % \
44            (regN, regno))
45    else:
46        f.write("    const int %s = insn->regno[%d];\n" % (regN, regno))
47    if ('A_CONDEXEC' in hex_common.attribdict[tag]):
48        f.write("    if (!is_preloaded(ctx, %s)) {\n" % regN)
49        f.write("        tcg_gen_mov_tl(hex_new_value[%s], hex_gpr[%s]);\n" % \
50                             (regN, regN))
51        f.write("    }\n")
52        f.write("    if (!is_preloaded(ctx, %s + 1)) {\n" % regN)
53        f.write("        tcg_gen_mov_tl(hex_new_value[%s + 1], hex_gpr[%s + 1]);\n" % \
54                             (regN, regN))
55        f.write("    }\n")
56
57def genptr_decl_writable(f, tag, regtype, regid, regno):
58    regN="%s%sN" % (regtype,regid)
59    f.write("    TCGv %s%sV = tcg_temp_local_new();\n" % \
60        (regtype, regid))
61    if (regtype == "C"):
62        f.write("    const int %s = insn->regno[%d] + HEX_REG_SA0;\n" % \
63            (regN, regno))
64    else:
65        f.write("    const int %s = insn->regno[%d];\n" % (regN, regno))
66    if ('A_CONDEXEC' in hex_common.attribdict[tag]):
67        f.write("    if (!is_preloaded(ctx, %s)) {\n" % regN)
68        f.write("        tcg_gen_mov_tl(hex_new_value[%s], hex_gpr[%s]);\n" % \
69                             (regN, regN))
70        f.write("    }\n")
71
72def genptr_decl(f, tag, regtype, regid, regno):
73    regN="%s%sN" % (regtype,regid)
74    if (regtype == "R"):
75        if (regid in {"ss", "tt"}):
76            f.write("    TCGv_i64 %s%sV = tcg_temp_local_new_i64();\n" % \
77                (regtype, regid))
78            f.write("    const int %s = insn->regno[%d];\n" % \
79                (regN, regno))
80        elif (regid in {"dd", "ee", "xx", "yy"}):
81            genptr_decl_pair_writable(f, tag, regtype, regid, regno)
82        elif (regid in {"s", "t", "u", "v"}):
83            f.write("    TCGv %s%sV = hex_gpr[insn->regno[%d]];\n" % \
84                (regtype, regid, regno))
85        elif (regid in {"d", "e", "x", "y"}):
86            genptr_decl_writable(f, tag, regtype, regid, regno)
87        else:
88            print("Bad register parse: ", regtype, regid)
89    elif (regtype == "P"):
90        if (regid in {"s", "t", "u", "v"}):
91            f.write("    TCGv %s%sV = hex_pred[insn->regno[%d]];\n" % \
92                (regtype, regid, regno))
93        elif (regid in {"d", "e", "x"}):
94            genptr_decl_writable(f, tag, regtype, regid, regno)
95        else:
96            print("Bad register parse: ", regtype, regid)
97    elif (regtype == "C"):
98        if (regid == "ss"):
99            f.write("    TCGv_i64 %s%sV = tcg_temp_local_new_i64();\n" % \
100                (regtype, regid))
101            f.write("    const int %s = insn->regno[%d] + HEX_REG_SA0;\n" % \
102                (regN, regno))
103        elif (regid == "dd"):
104            genptr_decl_pair_writable(f, tag, regtype, regid, regno)
105        elif (regid == "s"):
106            f.write("    TCGv %s%sV = tcg_temp_local_new();\n" % \
107                (regtype, regid))
108            f.write("    const int %s%sN = insn->regno[%d] + HEX_REG_SA0;\n" % \
109                (regtype, regid, regno))
110        elif (regid == "d"):
111            genptr_decl_writable(f, tag, regtype, regid, regno)
112        else:
113            print("Bad register parse: ", regtype, regid)
114    elif (regtype == "M"):
115        if (regid == "u"):
116            f.write("    const int %s%sN = insn->regno[%d];\n"% \
117                (regtype, regid, regno))
118            f.write("    TCGv %s%sV = hex_gpr[%s%sN + HEX_REG_M0];\n" % \
119                (regtype, regid, regtype, regid))
120        else:
121            print("Bad register parse: ", regtype, regid)
122    else:
123        print("Bad register parse: ", regtype, regid)
124
125def genptr_decl_new(f,regtype,regid,regno):
126    if (regtype == "N"):
127        if (regid in {"s", "t"}):
128            f.write("    TCGv %s%sN = hex_new_value[insn->regno[%d]];\n" % \
129                (regtype, regid, regno))
130        else:
131            print("Bad register parse: ", regtype, regid)
132    elif (regtype == "P"):
133        if (regid in {"t", "u", "v"}):
134            f.write("    TCGv %s%sN = hex_new_pred_value[insn->regno[%d]];\n" % \
135                (regtype, regid, regno))
136        else:
137            print("Bad register parse: ", regtype, regid)
138    else:
139        print("Bad register parse: ", regtype, regid)
140
141def genptr_decl_opn(f, tag, regtype, regid, toss, numregs, i):
142    if (hex_common.is_pair(regid)):
143        genptr_decl(f, tag, regtype, regid, i)
144    elif (hex_common.is_single(regid)):
145        if hex_common.is_old_val(regtype, regid, tag):
146            genptr_decl(f,tag, regtype, regid, i)
147        elif hex_common.is_new_val(regtype, regid, tag):
148            genptr_decl_new(f,regtype,regid,i)
149        else:
150            print("Bad register parse: ",regtype,regid,toss,numregs)
151    else:
152        print("Bad register parse: ",regtype,regid,toss,numregs)
153
154def genptr_decl_imm(f,immlett):
155    if (immlett.isupper()):
156        i = 1
157    else:
158        i = 0
159    f.write("    int %s = insn->immed[%d];\n" % \
160        (hex_common.imm_name(immlett), i))
161
162def genptr_free(f,regtype,regid,regno):
163    if (regtype == "R"):
164        if (regid in {"dd", "ss", "tt", "xx", "yy"}):
165            f.write("    tcg_temp_free_i64(%s%sV);\n" % (regtype, regid))
166        elif (regid in {"d", "e", "x", "y"}):
167            f.write("    tcg_temp_free(%s%sV);\n" % (regtype, regid))
168        elif (regid not in {"s", "t", "u", "v"}):
169            print("Bad register parse: ",regtype,regid)
170    elif (regtype == "P"):
171        if (regid in {"d", "e", "x"}):
172            f.write("    tcg_temp_free(%s%sV);\n" % (regtype, regid))
173        elif (regid not in {"s", "t", "u", "v"}):
174            print("Bad register parse: ",regtype,regid)
175    elif (regtype == "C"):
176        if (regid in {"dd", "ss"}):
177            f.write("    tcg_temp_free_i64(%s%sV);\n" % (regtype, regid))
178        elif (regid in {"d", "s"}):
179            f.write("    tcg_temp_free(%s%sV);\n" % (regtype, regid))
180        else:
181            print("Bad register parse: ",regtype,regid)
182    elif (regtype == "M"):
183        if (regid != "u"):
184            print("Bad register parse: ", regtype, regid)
185    else:
186        print("Bad register parse: ", regtype, regid)
187
188def genptr_free_new(f,regtype,regid,regno):
189    if (regtype == "N"):
190        if (regid not in {"s", "t"}):
191            print("Bad register parse: ", regtype, regid)
192    elif (regtype == "P"):
193        if (regid not in {"t", "u", "v"}):
194            print("Bad register parse: ", regtype, regid)
195    else:
196        print("Bad register parse: ", regtype, regid)
197
198def genptr_free_opn(f,regtype,regid,i,tag):
199    if (hex_common.is_pair(regid)):
200        genptr_free(f,regtype,regid,i)
201    elif (hex_common.is_single(regid)):
202        if hex_common.is_old_val(regtype, regid, tag):
203            genptr_free(f,regtype,regid,i)
204        elif hex_common.is_new_val(regtype, regid, tag):
205            genptr_free_new(f,regtype,regid,i)
206        else:
207            print("Bad register parse: ",regtype,regid,toss,numregs)
208    else:
209        print("Bad register parse: ",regtype,regid,toss,numregs)
210
211def genptr_src_read(f,regtype,regid):
212    if (regtype == "R"):
213        if (regid in {"ss", "tt", "xx", "yy"}):
214            f.write("    tcg_gen_concat_i32_i64(%s%sV, hex_gpr[%s%sN],\n" % \
215                (regtype, regid, regtype, regid))
216            f.write("                                 hex_gpr[%s%sN + 1]);\n" % \
217                (regtype, regid))
218        elif (regid in {"x", "y"}):
219            f.write("    tcg_gen_mov_tl(%s%sV, hex_gpr[%s%sN]);\n" % \
220                (regtype,regid,regtype,regid))
221        elif (regid not in {"s", "t", "u", "v"}):
222            print("Bad register parse: ", regtype, regid)
223    elif (regtype == "P"):
224        if (regid == "x"):
225            f.write("    tcg_gen_mov_tl(%s%sV, hex_pred[%s%sN]);\n" % \
226                (regtype, regid, regtype, regid))
227        elif (regid not in {"s", "t", "u", "v"}):
228            print("Bad register parse: ", regtype, regid)
229    elif (regtype == "C"):
230        if (regid == "ss"):
231            f.write("    gen_read_ctrl_reg_pair(ctx, %s%sN, %s%sV);\n" % \
232                             (regtype, regid, regtype, regid))
233        elif (regid == "s"):
234            f.write("    gen_read_ctrl_reg(ctx, %s%sN, %s%sV);\n" % \
235                             (regtype, regid, regtype, regid))
236        else:
237            print("Bad register parse: ", regtype, regid)
238    elif (regtype == "M"):
239        if (regid != "u"):
240            print("Bad register parse: ", regtype, regid)
241    else:
242        print("Bad register parse: ", regtype, regid)
243
244def genptr_src_read_new(f,regtype,regid):
245    if (regtype == "N"):
246        if (regid not in {"s", "t"}):
247            print("Bad register parse: ", regtype, regid)
248    elif (regtype == "P"):
249        if (regid not in {"t", "u", "v"}):
250            print("Bad register parse: ", regtype, regid)
251    else:
252        print("Bad register parse: ", regtype, regid)
253
254def genptr_src_read_opn(f,regtype,regid,tag):
255    if (hex_common.is_pair(regid)):
256        genptr_src_read(f,regtype,regid)
257    elif (hex_common.is_single(regid)):
258        if hex_common.is_old_val(regtype, regid, tag):
259            genptr_src_read(f,regtype,regid)
260        elif hex_common.is_new_val(regtype, regid, tag):
261            genptr_src_read_new(f,regtype,regid)
262        else:
263            print("Bad register parse: ",regtype,regid,toss,numregs)
264    else:
265        print("Bad register parse: ",regtype,regid,toss,numregs)
266
267def gen_helper_call_opn(f, tag, regtype, regid, toss, numregs, i):
268    if (i > 0): f.write(", ")
269    if (hex_common.is_pair(regid)):
270        f.write("%s%sV" % (regtype,regid))
271    elif (hex_common.is_single(regid)):
272        if hex_common.is_old_val(regtype, regid, tag):
273            f.write("%s%sV" % (regtype,regid))
274        elif hex_common.is_new_val(regtype, regid, tag):
275            f.write("%s%sN" % (regtype,regid))
276        else:
277            print("Bad register parse: ",regtype,regid,toss,numregs)
278    else:
279        print("Bad register parse: ",regtype,regid,toss,numregs)
280
281def gen_helper_decl_imm(f,immlett):
282    f.write("    TCGv tcgv_%s = tcg_constant_tl(%s);\n" % \
283        (hex_common.imm_name(immlett), hex_common.imm_name(immlett)))
284
285def gen_helper_call_imm(f,immlett):
286    f.write(", tcgv_%s" % hex_common.imm_name(immlett))
287
288def genptr_dst_write_pair(f, tag, regtype, regid):
289    if ('A_CONDEXEC' in hex_common.attribdict[tag]):
290        f.write("    gen_log_predicated_reg_write_pair(%s%sN, %s%sV, insn->slot);\n" % \
291            (regtype, regid, regtype, regid))
292    else:
293        f.write("    gen_log_reg_write_pair(%s%sN, %s%sV);\n" % \
294            (regtype, regid, regtype, regid))
295    f.write("    ctx_log_reg_write_pair(ctx, %s%sN);\n" % \
296        (regtype, regid))
297
298def genptr_dst_write(f, tag, regtype, regid):
299    if (regtype == "R"):
300        if (regid in {"dd", "xx", "yy"}):
301            genptr_dst_write_pair(f, tag, regtype, regid)
302        elif (regid in {"d", "e", "x", "y"}):
303            if ('A_CONDEXEC' in hex_common.attribdict[tag]):
304                f.write("    gen_log_predicated_reg_write(%s%sN, %s%sV,\n" % \
305                    (regtype, regid, regtype, regid))
306                f.write("                                 insn->slot);\n")
307            else:
308                f.write("    gen_log_reg_write(%s%sN, %s%sV);\n" % \
309                    (regtype, regid, regtype, regid))
310            f.write("    ctx_log_reg_write(ctx, %s%sN);\n" % \
311                (regtype, regid))
312        else:
313            print("Bad register parse: ", regtype, regid)
314    elif (regtype == "P"):
315        if (regid in {"d", "e", "x"}):
316            f.write("    gen_log_pred_write(ctx, %s%sN, %s%sV);\n" % \
317                (regtype, regid, regtype, regid))
318            f.write("    ctx_log_pred_write(ctx, %s%sN);\n" % \
319                (regtype, regid))
320        else:
321            print("Bad register parse: ", regtype, regid)
322    elif (regtype == "C"):
323        if (regid == "dd"):
324            f.write("    gen_write_ctrl_reg_pair(ctx, %s%sN, %s%sV);\n" % \
325                             (regtype, regid, regtype, regid))
326        elif (regid == "d"):
327            f.write("    gen_write_ctrl_reg(ctx, %s%sN, %s%sV);\n" % \
328                             (regtype, regid, regtype, regid))
329        else:
330            print("Bad register parse: ", regtype, regid)
331    else:
332        print("Bad register parse: ", regtype, regid)
333
334def genptr_dst_write_opn(f,regtype, regid, tag):
335    if (hex_common.is_pair(regid)):
336        genptr_dst_write(f, tag, regtype, regid)
337    elif (hex_common.is_single(regid)):
338        genptr_dst_write(f, tag, regtype, regid)
339    else:
340        print("Bad register parse: ",regtype,regid,toss,numregs)
341
342##
343## Generate the TCG code to call the helper
344##     For A2_add: Rd32=add(Rs32,Rt32), { RdV=RsV+RtV;}
345##     We produce:
346##    static void generate_A2_add()
347##                    CPUHexagonState *env
348##                    DisasContext *ctx,
349##                    Insn *insn,
350##                    Packet *pkt)
351##       {
352##           TCGv RdV = tcg_temp_local_new();
353##           const int RdN = insn->regno[0];
354##           TCGv RsV = hex_gpr[insn->regno[1]];
355##           TCGv RtV = hex_gpr[insn->regno[2]];
356##           <GEN>
357##           gen_log_reg_write(RdN, RdV);
358##           ctx_log_reg_write(ctx, RdN);
359##           tcg_temp_free(RdV);
360##       }
361##
362##       where <GEN> depends on hex_common.skip_qemu_helper(tag)
363##       if hex_common.skip_qemu_helper(tag) is True
364##       <GEN>  is fGEN_TCG_A2_add({ RdV=RsV+RtV;});
365##       if hex_common.skip_qemu_helper(tag) is False
366##       <GEN>  is gen_helper_A2_add(RdV, cpu_env, RsV, RtV);
367##
368def gen_tcg_func(f, tag, regs, imms):
369    f.write("static void generate_%s(\n" %tag)
370    f.write("                CPUHexagonState *env,\n")
371    f.write("                DisasContext *ctx,\n")
372    f.write("                Insn *insn,\n")
373    f.write("                Packet *pkt)\n")
374    f.write('{\n')
375    if hex_common.need_ea(tag): gen_decl_ea_tcg(f, tag)
376    i=0
377    ## Declare all the operands (regs and immediates)
378    for regtype,regid,toss,numregs in regs:
379        genptr_decl_opn(f, tag, regtype, regid, toss, numregs, i)
380        i += 1
381    for immlett,bits,immshift in imms:
382        genptr_decl_imm(f,immlett)
383
384    if 'A_PRIV' in hex_common.attribdict[tag]:
385        f.write('    fCHECKFORPRIV();\n')
386    if 'A_GUEST' in hex_common.attribdict[tag]:
387        f.write('    fCHECKFORGUEST();\n')
388
389    ## Read all the inputs
390    for regtype,regid,toss,numregs in regs:
391        if (hex_common.is_read(regid)):
392            genptr_src_read_opn(f,regtype,regid,tag)
393
394    if ( hex_common.skip_qemu_helper(tag) ):
395        f.write("    fGEN_TCG_%s(%s);\n" % (tag, hex_common.semdict[tag]))
396    else:
397        ## Generate the call to the helper
398        for immlett,bits,immshift in imms:
399            gen_helper_decl_imm(f,immlett)
400        if hex_common.need_part1(tag):
401            f.write("    TCGv part1 = tcg_constant_tl(insn->part1);\n")
402        if hex_common.need_slot(tag):
403            f.write("    TCGv slot = tcg_constant_tl(insn->slot);\n")
404        f.write("    gen_helper_%s(" % (tag))
405        i=0
406        ## If there is a scalar result, it is the return type
407        for regtype,regid,toss,numregs in regs:
408            if (hex_common.is_written(regid)):
409                gen_helper_call_opn(f, tag, regtype, regid, toss, numregs, i)
410                i += 1
411        if (i > 0): f.write(", ")
412        f.write("cpu_env")
413        i=1
414        for regtype,regid,toss,numregs in regs:
415            if (hex_common.is_read(regid)):
416                gen_helper_call_opn(f, tag, regtype, regid, toss, numregs, i)
417                i += 1
418        for immlett,bits,immshift in imms:
419            gen_helper_call_imm(f,immlett)
420
421        if hex_common.need_slot(tag): f.write(", slot")
422        if hex_common.need_part1(tag): f.write(", part1" )
423        f.write(");\n")
424
425    ## Write all the outputs
426    for regtype,regid,toss,numregs in regs:
427        if (hex_common.is_written(regid)):
428            genptr_dst_write_opn(f,regtype, regid, tag)
429
430    ## Free all the operands (regs and immediates)
431    if hex_common.need_ea(tag): gen_free_ea_tcg(f)
432    for regtype,regid,toss,numregs in regs:
433        genptr_free_opn(f,regtype,regid,i,tag)
434        i += 1
435
436    f.write("}\n\n")
437
438def gen_def_tcg_func(f, tag, tagregs, tagimms):
439    regs = tagregs[tag]
440    imms = tagimms[tag]
441
442    gen_tcg_func(f, tag, regs, imms)
443
444def main():
445    hex_common.read_semantics_file(sys.argv[1])
446    hex_common.read_attribs_file(sys.argv[2])
447    hex_common.read_overrides_file(sys.argv[3])
448    hex_common.calculate_attribs()
449    tagregs = hex_common.get_tagregs()
450    tagimms = hex_common.get_tagimms()
451
452    with open(sys.argv[4], 'w') as f:
453        f.write("#ifndef HEXAGON_TCG_FUNCS_H\n")
454        f.write("#define HEXAGON_TCG_FUNCS_H\n\n")
455
456        for tag in hex_common.tags:
457            ## Skip the priv instructions
458            if ( "A_PRIV" in hex_common.attribdict[tag] ) :
459                continue
460            ## Skip the guest instructions
461            if ( "A_GUEST" in hex_common.attribdict[tag] ) :
462                continue
463            ## Skip the diag instructions
464            if ( tag == "Y6_diag" ) :
465                continue
466            if ( tag == "Y6_diag0" ) :
467                continue
468            if ( tag == "Y6_diag1" ) :
469                continue
470
471            gen_def_tcg_func(f, tag, tagregs, tagimms)
472
473        f.write("#endif    /* HEXAGON_TCG_FUNCS_H */\n")
474
475if __name__ == "__main__":
476    main()
477