1#!/usr/bin/env python3
2
3##
4##  Copyright(c) 2019-2023 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##
27## Generate the TCG code to call the helper
28##     For A2_add: Rd32=add(Rs32,Rt32), { RdV=RsV+RtV;}
29##     We produce:
30##    static void generate_A2_add(DisasContext *ctx)
31##    {
32##        Insn *insn G_GNUC_UNUSED = ctx->insn;
33##        const int RdN = insn->regno[0];
34##        TCGv RdV = get_result_gpr(ctx, RdN);
35##        TCGv RsV = hex_gpr[insn->regno[1]];
36##        TCGv RtV = hex_gpr[insn->regno[2]];
37##        <GEN>
38##        gen_log_reg_write(ctx, RdN, RdV);
39##    }
40##
41##       where <GEN> depends on hex_common.skip_qemu_helper(tag)
42##       if hex_common.skip_qemu_helper(tag) is True
43##       <GEN>  is fGEN_TCG_A2_add({ RdV=RsV+RtV;});
44##       if hex_common.skip_qemu_helper(tag) is False
45##       <GEN>  is gen_helper_A2_add(RdV, tcg_env, RsV, RtV);
46##
47def gen_tcg_func(f, tag, regs, imms):
48    f.write(f"static void generate_{tag}(DisasContext *ctx)\n")
49    f.write("{\n")
50
51    f.write("    Insn *insn G_GNUC_UNUSED = ctx->insn;\n")
52
53    if hex_common.need_ea(tag):
54        f.write("    TCGv EA G_GNUC_UNUSED = tcg_temp_new();\n")
55
56    ## Declare all the operands (regs and immediates)
57    i = 0
58    for regtype, regid in regs:
59        reg = hex_common.get_register(tag, regtype, regid)
60        reg.decl_tcg(f, tag, i)
61        i += 1
62    for immlett, bits, immshift in imms:
63        i = 1 if immlett.isupper() else 0
64        f.write(f"    int {hex_common.imm_name(immlett)} = insn->immed[{i}];\n")
65
66    if hex_common.is_idef_parser_enabled(tag):
67        declared = []
68        ## Handle registers
69        for regtype, regid in regs:
70            reg = hex_common.get_register(tag, regtype, regid)
71            reg.idef_arg(declared)
72        ## Handle immediates
73        for immlett, bits, immshift in imms:
74            declared.append(hex_common.imm_name(immlett))
75
76        arguments = ", ".join(["ctx", "ctx->insn", "ctx->pkt"] + declared)
77        f.write(f"    emit_{tag}({arguments});\n")
78
79    elif hex_common.skip_qemu_helper(tag):
80        f.write(f"    fGEN_TCG_{tag}({hex_common.semdict[tag]});\n")
81    else:
82        ## Generate the call to the helper
83        declared = []
84        ret_type = hex_common.helper_ret_type(tag, regs).call_arg
85        if ret_type != "void":
86            declared.append(ret_type)
87
88        for arg in hex_common.helper_args(tag, regs, imms):
89            declared.append(arg.call_arg)
90
91        arguments = ", ".join(declared)
92        f.write(f"    gen_helper_{tag}({arguments});\n")
93
94    ## Write all the outputs
95    for regtype, regid in regs:
96        reg = hex_common.get_register(tag, regtype, regid)
97        if reg.is_written():
98            reg.log_write(f, tag)
99
100    f.write("}\n\n")
101
102
103def gen_def_tcg_func(f, tag, tagregs, tagimms):
104    regs = tagregs[tag]
105    imms = tagimms[tag]
106
107    gen_tcg_func(f, tag, regs, imms)
108
109
110def main():
111    hex_common.read_semantics_file(sys.argv[1])
112    hex_common.read_attribs_file(sys.argv[2])
113    hex_common.read_overrides_file(sys.argv[3])
114    hex_common.read_overrides_file(sys.argv[4])
115    hex_common.calculate_attribs()
116    hex_common.init_registers()
117    ## Whether or not idef-parser is enabled is
118    ## determined by the number of arguments to
119    ## this script:
120    ##
121    ##   5 args. -> not enabled,
122    ##   6 args. -> idef-parser enabled.
123    ##
124    ## The 6:th arg. then holds a list of the successfully
125    ## parsed instructions.
126    is_idef_parser_enabled = len(sys.argv) > 6
127    if is_idef_parser_enabled:
128        hex_common.read_idef_parser_enabled_file(sys.argv[5])
129    tagregs = hex_common.get_tagregs()
130    tagimms = hex_common.get_tagimms()
131
132    output_file = sys.argv[-1]
133    with open(output_file, "w") as f:
134        f.write("#ifndef HEXAGON_TCG_FUNCS_H\n")
135        f.write("#define HEXAGON_TCG_FUNCS_H\n\n")
136        if is_idef_parser_enabled:
137            f.write('#include "idef-generated-emitter.h.inc"\n\n')
138
139        for tag in hex_common.tags:
140            ## Skip the priv instructions
141            if "A_PRIV" in hex_common.attribdict[tag]:
142                continue
143            ## Skip the guest instructions
144            if "A_GUEST" in hex_common.attribdict[tag]:
145                continue
146            ## Skip the diag instructions
147            if tag == "Y6_diag":
148                continue
149            if tag == "Y6_diag0":
150                continue
151            if tag == "Y6_diag1":
152                continue
153
154            gen_def_tcg_func(f, tag, tagregs, tagimms)
155
156        f.write("#endif    /* HEXAGON_TCG_FUNCS_H */\n")
157
158
159if __name__ == "__main__":
160    main()
161