xref: /qemu/target/hexagon/gen_tcg_funcs.py (revision 0955d66e)
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_const_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 gen_helper_free_imm(f,immlett):
289    f.write("    tcg_temp_free(tcgv_%s);\n" % hex_common.imm_name(immlett))
290
291def genptr_dst_write_pair(f, tag, regtype, regid):
292    if ('A_CONDEXEC' in hex_common.attribdict[tag]):
293        f.write("    gen_log_predicated_reg_write_pair(%s%sN, %s%sV, insn->slot);\n" % \
294            (regtype, regid, regtype, regid))
295    else:
296        f.write("    gen_log_reg_write_pair(%s%sN, %s%sV);\n" % \
297            (regtype, regid, regtype, regid))
298    f.write("    ctx_log_reg_write_pair(ctx, %s%sN);\n" % \
299        (regtype, regid))
300
301def genptr_dst_write(f, tag, regtype, regid):
302    if (regtype == "R"):
303        if (regid in {"dd", "xx", "yy"}):
304            genptr_dst_write_pair(f, tag, regtype, regid)
305        elif (regid in {"d", "e", "x", "y"}):
306            if ('A_CONDEXEC' in hex_common.attribdict[tag]):
307                f.write("    gen_log_predicated_reg_write(%s%sN, %s%sV,\n" % \
308                    (regtype, regid, regtype, regid))
309                f.write("                                 insn->slot);\n")
310            else:
311                f.write("    gen_log_reg_write(%s%sN, %s%sV);\n" % \
312                    (regtype, regid, regtype, regid))
313            f.write("    ctx_log_reg_write(ctx, %s%sN);\n" % \
314                (regtype, regid))
315        else:
316            print("Bad register parse: ", regtype, regid)
317    elif (regtype == "P"):
318        if (regid in {"d", "e", "x"}):
319            f.write("    gen_log_pred_write(ctx, %s%sN, %s%sV);\n" % \
320                (regtype, regid, regtype, regid))
321            f.write("    ctx_log_pred_write(ctx, %s%sN);\n" % \
322                (regtype, regid))
323        else:
324            print("Bad register parse: ", regtype, regid)
325    elif (regtype == "C"):
326        if (regid == "dd"):
327            f.write("    gen_write_ctrl_reg_pair(ctx, %s%sN, %s%sV);\n" % \
328                             (regtype, regid, regtype, regid))
329        elif (regid == "d"):
330            f.write("    gen_write_ctrl_reg(ctx, %s%sN, %s%sV);\n" % \
331                             (regtype, regid, regtype, regid))
332        else:
333            print("Bad register parse: ", regtype, regid)
334    else:
335        print("Bad register parse: ", regtype, regid)
336
337def genptr_dst_write_opn(f,regtype, regid, tag):
338    if (hex_common.is_pair(regid)):
339        genptr_dst_write(f, tag, regtype, regid)
340    elif (hex_common.is_single(regid)):
341        genptr_dst_write(f, tag, regtype, regid)
342    else:
343        print("Bad register parse: ",regtype,regid,toss,numregs)
344
345##
346## Generate the TCG code to call the helper
347##     For A2_add: Rd32=add(Rs32,Rt32), { RdV=RsV+RtV;}
348##     We produce:
349##    static void generate_A2_add()
350##                    CPUHexagonState *env
351##                    DisasContext *ctx,
352##                    Insn *insn,
353##                    Packet *pkt)
354##       {
355##           TCGv RdV = tcg_temp_local_new();
356##           const int RdN = insn->regno[0];
357##           TCGv RsV = hex_gpr[insn->regno[1]];
358##           TCGv RtV = hex_gpr[insn->regno[2]];
359##           <GEN>
360##           gen_log_reg_write(RdN, RdV);
361##           ctx_log_reg_write(ctx, RdN);
362##           tcg_temp_free(RdV);
363##       }
364##
365##       where <GEN> depends on hex_common.skip_qemu_helper(tag)
366##       if hex_common.skip_qemu_helper(tag) is True
367##       <GEN>  is fGEN_TCG_A2_add({ RdV=RsV+RtV;});
368##       if hex_common.skip_qemu_helper(tag) is False
369##       <GEN>  is gen_helper_A2_add(RdV, cpu_env, RsV, RtV);
370##
371def gen_tcg_func(f, tag, regs, imms):
372    f.write("static void generate_%s(\n" %tag)
373    f.write("                CPUHexagonState *env,\n")
374    f.write("                DisasContext *ctx,\n")
375    f.write("                Insn *insn,\n")
376    f.write("                Packet *pkt)\n")
377    f.write('{\n')
378    if hex_common.need_ea(tag): gen_decl_ea_tcg(f, tag)
379    i=0
380    ## Declare all the operands (regs and immediates)
381    for regtype,regid,toss,numregs in regs:
382        genptr_decl_opn(f, tag, regtype, regid, toss, numregs, i)
383        i += 1
384    for immlett,bits,immshift in imms:
385        genptr_decl_imm(f,immlett)
386
387    if 'A_PRIV' in hex_common.attribdict[tag]:
388        f.write('    fCHECKFORPRIV();\n')
389    if 'A_GUEST' in hex_common.attribdict[tag]:
390        f.write('    fCHECKFORGUEST();\n')
391
392    ## Read all the inputs
393    for regtype,regid,toss,numregs in regs:
394        if (hex_common.is_read(regid)):
395            genptr_src_read_opn(f,regtype,regid,tag)
396
397    if ( hex_common.skip_qemu_helper(tag) ):
398        f.write("    fGEN_TCG_%s(%s);\n" % (tag, hex_common.semdict[tag]))
399    else:
400        ## Generate the call to the helper
401        for immlett,bits,immshift in imms:
402            gen_helper_decl_imm(f,immlett)
403        if hex_common.need_part1(tag):
404            f.write("    TCGv part1 = tcg_const_tl(insn->part1);\n")
405        if hex_common.need_slot(tag):
406            f.write("    TCGv slot = tcg_constant_tl(insn->slot);\n")
407        f.write("    gen_helper_%s(" % (tag))
408        i=0
409        ## If there is a scalar result, it is the return type
410        for regtype,regid,toss,numregs in regs:
411            if (hex_common.is_written(regid)):
412                gen_helper_call_opn(f, tag, regtype, regid, toss, numregs, i)
413                i += 1
414        if (i > 0): f.write(", ")
415        f.write("cpu_env")
416        i=1
417        for regtype,regid,toss,numregs in regs:
418            if (hex_common.is_read(regid)):
419                gen_helper_call_opn(f, tag, regtype, regid, toss, numregs, i)
420                i += 1
421        for immlett,bits,immshift in imms:
422            gen_helper_call_imm(f,immlett)
423
424        if hex_common.need_slot(tag): f.write(", slot")
425        if hex_common.need_part1(tag): f.write(", part1" )
426        f.write(");\n")
427        if hex_common.need_part1(tag):
428            f.write("    tcg_temp_free(part1);\n")
429        for immlett,bits,immshift in imms:
430            gen_helper_free_imm(f,immlett)
431
432    ## Write all the outputs
433    for regtype,regid,toss,numregs in regs:
434        if (hex_common.is_written(regid)):
435            genptr_dst_write_opn(f,regtype, regid, tag)
436
437    ## Free all the operands (regs and immediates)
438    if hex_common.need_ea(tag): gen_free_ea_tcg(f)
439    for regtype,regid,toss,numregs in regs:
440        genptr_free_opn(f,regtype,regid,i,tag)
441        i += 1
442
443    f.write("}\n\n")
444
445def gen_def_tcg_func(f, tag, tagregs, tagimms):
446    regs = tagregs[tag]
447    imms = tagimms[tag]
448
449    gen_tcg_func(f, tag, regs, imms)
450
451def main():
452    hex_common.read_semantics_file(sys.argv[1])
453    hex_common.read_attribs_file(sys.argv[2])
454    hex_common.read_overrides_file(sys.argv[3])
455    hex_common.calculate_attribs()
456    tagregs = hex_common.get_tagregs()
457    tagimms = hex_common.get_tagimms()
458
459    with open(sys.argv[4], 'w') as f:
460        f.write("#ifndef HEXAGON_TCG_FUNCS_H\n")
461        f.write("#define HEXAGON_TCG_FUNCS_H\n\n")
462
463        for tag in hex_common.tags:
464            ## Skip the priv instructions
465            if ( "A_PRIV" in hex_common.attribdict[tag] ) :
466                continue
467            ## Skip the guest instructions
468            if ( "A_GUEST" in hex_common.attribdict[tag] ) :
469                continue
470            ## Skip the diag instructions
471            if ( tag == "Y6_diag" ) :
472                continue
473            if ( tag == "Y6_diag0" ) :
474                continue
475            if ( tag == "Y6_diag1" ) :
476                continue
477
478            gen_def_tcg_func(f, tag, tagregs, tagimms)
479
480        f.write("#endif    /* HEXAGON_TCG_FUNCS_H */\n")
481
482if __name__ == "__main__":
483    main()
484