master
py 183 lines 6.01 KB
Raw
1 #!/usr/bin/env python3
2
3 ##
4 ## Copyright(c) 2019-2024 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
20 import sys
21 import re
22 import string
23 import hex_common
24 from textwrap import dedent
25
26 def gen_disabled_ieee_insn(f, tag, regs):
27 f.write(" if (!ctx->ieee_fp_extension) {\n")
28 for regtype, regid in regs:
29 reg = hex_common.get_register(tag, regtype, regid)
30 if reg.is_hvx_reg() and reg.is_written():
31 reg.gen_zero(f)
32 f.write(" return;\n")
33 f.write(" }\n")
34
35 ##
36 ## Generate the TCG code to call the helper
37 ## For A2_add: Rd32=add(Rs32,Rt32), { RdV=RsV+RtV;}
38 ## We produce:
39 ## static void generate_A2_add(DisasContext *ctx)
40 ## {
41 ## Insn *insn G_GNUC_UNUSED = ctx->insn;
42 ## const int RdN = insn->regno[0];
43 ## TCGv RdV = get_result_gpr(ctx, RdN);
44 ## TCGv RsV = hex_gpr[insn->regno[1]];
45 ## TCGv RtV = hex_gpr[insn->regno[2]];
46 ## <GEN>
47 ## }
48 ##
49 ## where <GEN> depends on hex_common.skip_qemu_helper(tag)
50 ## if hex_common.skip_qemu_helper(tag) is True
51 ## <GEN> is fGEN_TCG_A2_add({ RdV=RsV+RtV;});
52 ## if hex_common.skip_qemu_helper(tag) is False
53 ## <GEN> is gen_helper_A2_add(RdV, tcg_env, RsV, RtV);
54 ##
55 def gen_tcg_func(f, tag, regs, imms):
56 f.write(f"static void generate_{tag}(DisasContext *ctx)\n")
57 f.write("{\n")
58
59 f.write(" Insn *insn G_GNUC_UNUSED = ctx->insn;\n")
60
61 if "A_PRIV" in hex_common.attribdict[tag]:
62 f.write(dedent("""\
63 #ifdef CONFIG_USER_ONLY
64 hex_gen_exception_end_tb(ctx, HEX_CAUSE_PRIV_USER_NO_SINSN);
65 #else
66 """))
67 if "A_GUEST" in hex_common.attribdict[tag]:
68 f.write(dedent("""\
69 #ifdef CONFIG_USER_ONLY
70 hex_gen_exception_end_tb(ctx, HEX_CAUSE_PRIV_USER_NO_GINSN);
71 #else
72 """))
73 if hex_common.need_ea(tag):
74 f.write(" TCGv EA G_GNUC_UNUSED = tcg_temp_new();\n")
75
76 ## Declare all the operands (regs and immediates)
77 i = 0
78 for regtype, regid in regs:
79 reg = hex_common.get_register(tag, regtype, regid)
80 reg.decl_tcg(f, tag, i)
81 i += 1
82 for immlett, bits, immshift in imms:
83 i = 1 if immlett.isupper() else 0
84 f.write(f" int {hex_common.imm_name(immlett)} = insn->immed[{i}];\n")
85
86 if "A_HVX_IEEE_FP" in hex_common.attribdict[tag]:
87 gen_disabled_ieee_insn(f, tag, regs)
88
89 if hex_common.is_idef_parser_enabled(tag):
90 gpr_operands = [
91 hex_common.get_register(tag, regtype, regid)
92 for regtype, regid in regs
93 if hex_common.get_register(tag, regtype, regid).may_alias_gpr()
94 ]
95 dests = [reg for reg in gpr_operands if reg.is_written()]
96 for reg in gpr_operands:
97 if reg.is_written() or not reg.is_read():
98 continue
99 src = reg.reg_tcg()
100 for dest in dests:
101 f.write(hex_common.code_fmt(f"""\
102 {src} = gen_unalias_gpr_src({src}, {dest.reg_tcg()});
103 """))
104
105 declared = []
106 ## Handle registers
107 for regtype, regid in regs:
108 reg = hex_common.get_register(tag, regtype, regid)
109 reg.idef_arg(declared)
110 ## Handle immediates
111 for immlett, bits, immshift in imms:
112 declared.append(hex_common.imm_name(immlett))
113
114 arguments = ", ".join(["ctx", "ctx->insn", "&ctx->pkt"] + declared)
115 f.write(f" emit_{tag}({arguments});\n")
116
117 elif hex_common.skip_qemu_helper(tag):
118 if "A_FPOP" in hex_common.attribdict[tag]:
119 f.write(" TCGv pkt_need_commit = ")
120 f.write("tcg_constant_tl(ctx->need_commit);\n")
121
122 f.write(f" fGEN_TCG_{tag}({hex_common.semdict[tag]});\n")
123 else:
124 ## Generate the call to the helper
125 declared = []
126 ret_type = hex_common.helper_ret_type(tag, regs).call_arg
127 if ret_type != "void":
128 declared.append(ret_type)
129
130 for arg in hex_common.helper_args(tag, regs, imms):
131 declared.append(arg.call_arg)
132
133 arguments = ", ".join(declared)
134 f.write(f" gen_helper_{tag}({arguments});\n")
135
136 ## Write all the outputs
137 for regtype, regid in regs:
138 reg = hex_common.get_register(tag, regtype, regid)
139 if reg.is_written():
140 reg.gen_write(f, tag)
141
142 if (
143 "A_PRIV" in hex_common.attribdict[tag]
144 or "A_GUEST" in hex_common.attribdict[tag]
145 ):
146 f.write("#endif /* CONFIG_USER_ONLY */\n")
147 f.write("}\n\n")
148
149
150 def gen_def_tcg_func(f, tag, tagregs, tagimms):
151 regs = tagregs[tag]
152 imms = tagimms[tag]
153
154 gen_tcg_func(f, tag, regs, imms)
155
156
157 def main():
158 args = hex_common.parse_common_args(
159 "Emit functions calling generated code implementing instruction semantics (helpers, idef-parser)"
160 )
161 tagregs = hex_common.get_tagregs()
162 tagimms = hex_common.get_tagimms()
163
164 with open(args.out, "w") as f:
165 f.write("#ifndef HEXAGON_TCG_FUNCS_H\n")
166 f.write("#define HEXAGON_TCG_FUNCS_H\n\n")
167 if args.idef_parser:
168 f.write('#include "idef-generated-emitter.h.inc"\n\n')
169
170 for tag in hex_common.tags:
171 if hex_common.tag_ignore(tag):
172 f.write(f"static void generate_{tag}"
173 f"(DisasContext *ctx)\n")
174 f.write("{\n}\n\n")
175 continue
176
177 gen_def_tcg_func(f, tag, tagregs, tagimms)
178
179 f.write("#endif /* HEXAGON_TCG_FUNCS_H */\n")
180
181
182 if __name__ == "__main__":
183 main()