]>
Commit | Line | Data |
---|---|---|
793958c9 TS |
1 | #!/usr/bin/env python3 |
2 | ||
3 | ## | |
10849c26 | 4 | ## Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. |
793958c9 TS |
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 | ||
5bb322e2 | 25 | |
793958c9 TS |
26 | ## |
27 | ## Helpers for gen_tcg_func | |
28 | ## | |
29 | def gen_decl_ea_tcg(f, tag): | |
6bf4bbc1 | 30 | f.write(" TCGv EA G_GNUC_UNUSED = tcg_temp_new();\n") |
793958c9 | 31 | |
5bb322e2 | 32 | |
fc253f4a | 33 | def genptr_decl_pair_writable(f, tag, regtype, regid, regno): |
5bb322e2 ML |
34 | regN = f"{regtype}{regid}N" |
35 | if regtype == "R": | |
cd6c4edf | 36 | f.write(f" const int {regN} = insn->regno[{regno}];\n") |
5bb322e2 | 37 | elif regtype == "C": |
cd6c4edf | 38 | f.write(f" const int {regN} = insn->regno[{regno}] + HEX_REG_SA0;\n") |
793958c9 | 39 | else: |
e28b77a6 | 40 | print("Bad register parse: ", regtype, regid) |
5bb322e2 ML |
41 | f.write(f" TCGv_i64 {regtype}{regid}V = " f"get_result_gpr_pair(ctx, {regN});\n") |
42 | ||
793958c9 | 43 | |
fc253f4a | 44 | def genptr_decl_writable(f, tag, regtype, regid, regno): |
5bb322e2 ML |
45 | regN = f"{regtype}{regid}N" |
46 | if regtype == "R": | |
cd6c4edf ML |
47 | f.write(f" const int {regN} = insn->regno[{regno}];\n") |
48 | f.write(f" TCGv {regtype}{regid}V = get_result_gpr(ctx, {regN});\n") | |
5bb322e2 | 49 | elif regtype == "C": |
cd6c4edf ML |
50 | f.write(f" const int {regN} = insn->regno[{regno}] + HEX_REG_SA0;\n") |
51 | f.write(f" TCGv {regtype}{regid}V = get_result_gpr(ctx, {regN});\n") | |
5bb322e2 | 52 | elif regtype == "P": |
cd6c4edf ML |
53 | f.write(f" const int {regN} = insn->regno[{regno}];\n") |
54 | f.write(f" TCGv {regtype}{regid}V = tcg_temp_new();\n") | |
e28b77a6 TS |
55 | else: |
56 | print("Bad register parse: ", regtype, regid) | |
793958c9 | 57 | |
5bb322e2 | 58 | |
793958c9 | 59 | def genptr_decl(f, tag, regtype, regid, regno): |
5bb322e2 ML |
60 | regN = f"{regtype}{regid}N" |
61 | if regtype == "R": | |
62 | if regid in {"ss", "tt"}: | |
cd6c4edf ML |
63 | f.write(f" TCGv_i64 {regtype}{regid}V = tcg_temp_new_i64();\n") |
64 | f.write(f" const int {regN} = insn->regno[{regno}];\n") | |
5bb322e2 | 65 | elif regid in {"dd", "ee", "xx", "yy"}: |
fc253f4a | 66 | genptr_decl_pair_writable(f, tag, regtype, regid, regno) |
5bb322e2 ML |
67 | elif regid in {"s", "t", "u", "v"}: |
68 | f.write( | |
69 | f" TCGv {regtype}{regid}V = " f"hex_gpr[insn->regno[{regno}]];\n" | |
70 | ) | |
71 | elif regid in {"d", "e", "x", "y"}: | |
fc253f4a | 72 | genptr_decl_writable(f, tag, regtype, regid, regno) |
793958c9 TS |
73 | else: |
74 | print("Bad register parse: ", regtype, regid) | |
5bb322e2 ML |
75 | elif regtype == "P": |
76 | if regid in {"s", "t", "u", "v"}: | |
77 | f.write( | |
78 | f" TCGv {regtype}{regid}V = " f"hex_pred[insn->regno[{regno}]];\n" | |
79 | ) | |
80 | elif regid in {"d", "e", "x"}: | |
fc253f4a | 81 | genptr_decl_writable(f, tag, regtype, regid, regno) |
793958c9 TS |
82 | else: |
83 | print("Bad register parse: ", regtype, regid) | |
5bb322e2 ML |
84 | elif regtype == "C": |
85 | if regid == "ss": | |
86 | f.write(f" TCGv_i64 {regtype}{regid}V = " f"tcg_temp_new_i64();\n") | |
87 | f.write(f" const int {regN} = insn->regno[{regno}] + " "HEX_REG_SA0;\n") | |
88 | elif regid == "dd": | |
fc253f4a | 89 | genptr_decl_pair_writable(f, tag, regtype, regid, regno) |
5bb322e2 | 90 | elif regid == "s": |
cd6c4edf | 91 | f.write(f" TCGv {regtype}{regid}V = tcg_temp_new();\n") |
5bb322e2 ML |
92 | f.write( |
93 | f" const int {regtype}{regid}N = insn->regno[{regno}] + " | |
94 | "HEX_REG_SA0;\n" | |
95 | ) | |
96 | elif regid == "d": | |
fc253f4a | 97 | genptr_decl_writable(f, tag, regtype, regid, regno) |
793958c9 TS |
98 | else: |
99 | print("Bad register parse: ", regtype, regid) | |
5bb322e2 ML |
100 | elif regtype == "M": |
101 | if regid == "u": | |
102 | f.write(f" const int {regtype}{regid}N = " f"insn->regno[{regno}];\n") | |
103 | f.write( | |
104 | f" TCGv {regtype}{regid}V = hex_gpr[{regtype}{regid}N + " | |
105 | "HEX_REG_M0];\n" | |
106 | ) | |
793958c9 TS |
107 | else: |
108 | print("Bad register parse: ", regtype, regid) | |
5bb322e2 ML |
109 | elif regtype == "V": |
110 | if regid in {"dd"}: | |
111 | f.write(f" const int {regtype}{regid}N = " f"insn->regno[{regno}];\n") | |
cd6c4edf | 112 | f.write(f" const intptr_t {regtype}{regid}V_off =\n") |
5bb322e2 ML |
113 | if hex_common.is_tmp_result(tag): |
114 | f.write( | |
115 | f" ctx_tmp_vreg_off(ctx, {regtype}{regid}N, 2, " "true);\n" | |
116 | ) | |
ccd9eec8 | 117 | else: |
cd6c4edf | 118 | f.write(f" ctx_future_vreg_off(ctx, {regtype}{regid}N,") |
ccd9eec8 | 119 | f.write(" 2, true);\n") |
5bb322e2 ML |
120 | if not hex_common.skip_qemu_helper(tag): |
121 | f.write(f" TCGv_ptr {regtype}{regid}V = " "tcg_temp_new_ptr();\n") | |
122 | f.write( | |
123 | f" tcg_gen_addi_ptr({regtype}{regid}V, cpu_env, " | |
124 | f"{regtype}{regid}V_off);\n" | |
125 | ) | |
126 | elif regid in {"uu", "vv", "xx"}: | |
127 | f.write(f" const int {regtype}{regid}N = " f"insn->regno[{regno}];\n") | |
cd6c4edf ML |
128 | f.write(f" const intptr_t {regtype}{regid}V_off =\n") |
129 | f.write(f" offsetof(CPUHexagonState, {regtype}{regid}V);\n") | |
5bb322e2 ML |
130 | if not hex_common.skip_qemu_helper(tag): |
131 | f.write(f" TCGv_ptr {regtype}{regid}V = " "tcg_temp_new_ptr();\n") | |
132 | f.write( | |
133 | f" tcg_gen_addi_ptr({regtype}{regid}V, cpu_env, " | |
134 | f"{regtype}{regid}V_off);\n" | |
135 | ) | |
136 | elif regid in {"s", "u", "v", "w"}: | |
137 | f.write(f" const int {regtype}{regid}N = " f"insn->regno[{regno}];\n") | |
cd6c4edf ML |
138 | f.write(f" const intptr_t {regtype}{regid}V_off =\n") |
139 | f.write(f" vreg_src_off(ctx, {regtype}{regid}N);\n") | |
5bb322e2 ML |
140 | if not hex_common.skip_qemu_helper(tag): |
141 | f.write(f" TCGv_ptr {regtype}{regid}V = " "tcg_temp_new_ptr();\n") | |
142 | elif regid in {"d", "x", "y"}: | |
143 | f.write(f" const int {regtype}{regid}N = " f"insn->regno[{regno}];\n") | |
cd6c4edf | 144 | f.write(f" const intptr_t {regtype}{regid}V_off =\n") |
5bb322e2 | 145 | if regid == "y": |
1e814a0d | 146 | f.write(" offsetof(CPUHexagonState, vtmp);\n") |
5bb322e2 ML |
147 | elif hex_common.is_tmp_result(tag): |
148 | f.write( | |
149 | f" ctx_tmp_vreg_off(ctx, {regtype}{regid}N, 1, " "true);\n" | |
150 | ) | |
ccd9eec8 | 151 | else: |
cd6c4edf | 152 | f.write(f" ctx_future_vreg_off(ctx, {regtype}{regid}N,") |
5bb322e2 | 153 | f.write(" 1, true);\n") |
83853ea0 | 154 | |
5bb322e2 ML |
155 | if not hex_common.skip_qemu_helper(tag): |
156 | f.write(f" TCGv_ptr {regtype}{regid}V = " "tcg_temp_new_ptr();\n") | |
157 | f.write( | |
158 | f" tcg_gen_addi_ptr({regtype}{regid}V, cpu_env, " | |
159 | f"{regtype}{regid}V_off);\n" | |
160 | ) | |
ccd9eec8 TS |
161 | else: |
162 | print("Bad register parse: ", regtype, regid) | |
5bb322e2 ML |
163 | elif regtype == "Q": |
164 | if regid in {"d", "e", "x"}: | |
165 | f.write(f" const int {regtype}{regid}N = " f"insn->regno[{regno}];\n") | |
cd6c4edf ML |
166 | f.write(f" const intptr_t {regtype}{regid}V_off =\n") |
167 | f.write(f" get_result_qreg(ctx, {regtype}{regid}N);\n") | |
5bb322e2 ML |
168 | if not hex_common.skip_qemu_helper(tag): |
169 | f.write(f" TCGv_ptr {regtype}{regid}V = " "tcg_temp_new_ptr();\n") | |
170 | f.write( | |
171 | f" tcg_gen_addi_ptr({regtype}{regid}V, cpu_env, " | |
172 | f"{regtype}{regid}V_off);\n" | |
173 | ) | |
174 | elif regid in {"s", "t", "u", "v"}: | |
175 | f.write(f" const int {regtype}{regid}N = " f"insn->regno[{regno}];\n") | |
cd6c4edf | 176 | f.write(f" const intptr_t {regtype}{regid}V_off =\n") |
5bb322e2 ML |
177 | f.write( |
178 | f" offsetof(CPUHexagonState, " f"QRegs[{regtype}{regid}N]);\n" | |
179 | ) | |
180 | if not hex_common.skip_qemu_helper(tag): | |
181 | f.write(f" TCGv_ptr {regtype}{regid}V = " "tcg_temp_new_ptr();\n") | |
ccd9eec8 TS |
182 | else: |
183 | print("Bad register parse: ", regtype, regid) | |
793958c9 TS |
184 | else: |
185 | print("Bad register parse: ", regtype, regid) | |
186 | ||
5bb322e2 | 187 | |
ccd9eec8 | 188 | def genptr_decl_new(f, tag, regtype, regid, regno): |
5bb322e2 ML |
189 | if regtype == "N": |
190 | if regid in {"s", "t"}: | |
191 | f.write( | |
192 | f" TCGv {regtype}{regid}N = " | |
6aa4f1d1 | 193 | f"get_result_gpr(ctx, insn->regno[{regno}]);\n" |
5bb322e2 | 194 | ) |
793958c9 TS |
195 | else: |
196 | print("Bad register parse: ", regtype, regid) | |
5bb322e2 ML |
197 | elif regtype == "P": |
198 | if regid in {"t", "u", "v"}: | |
199 | f.write( | |
200 | f" TCGv {regtype}{regid}N = " | |
201 | f"hex_new_pred_value[insn->regno[{regno}]];\n" | |
202 | ) | |
793958c9 TS |
203 | else: |
204 | print("Bad register parse: ", regtype, regid) | |
5bb322e2 ML |
205 | elif regtype == "O": |
206 | if regid == "s": | |
207 | f.write( | |
208 | f" const intptr_t {regtype}{regid}N_num = " | |
209 | f"insn->regno[{regno}];\n" | |
210 | ) | |
211 | if hex_common.skip_qemu_helper(tag): | |
cd6c4edf | 212 | f.write(f" const intptr_t {regtype}{regid}N_off =\n") |
5bb322e2 | 213 | f.write(" ctx_future_vreg_off(ctx, " f"{regtype}{regid}N_num,") |
ccd9eec8 TS |
214 | f.write(" 1, true);\n") |
215 | else: | |
5bb322e2 ML |
216 | f.write( |
217 | f" TCGv {regtype}{regid}N = " | |
218 | f"tcg_constant_tl({regtype}{regid}N_num);\n" | |
219 | ) | |
ccd9eec8 TS |
220 | else: |
221 | print("Bad register parse: ", regtype, regid) | |
793958c9 TS |
222 | else: |
223 | print("Bad register parse: ", regtype, regid) | |
224 | ||
5bb322e2 | 225 | |
793958c9 | 226 | def genptr_decl_opn(f, tag, regtype, regid, toss, numregs, i): |
5bb322e2 | 227 | if hex_common.is_pair(regid): |
793958c9 | 228 | genptr_decl(f, tag, regtype, regid, i) |
5bb322e2 | 229 | elif hex_common.is_single(regid): |
793958c9 | 230 | if hex_common.is_old_val(regtype, regid, tag): |
5bb322e2 | 231 | genptr_decl(f, tag, regtype, regid, i) |
793958c9 | 232 | elif hex_common.is_new_val(regtype, regid, tag): |
ccd9eec8 | 233 | genptr_decl_new(f, tag, regtype, regid, i) |
793958c9 | 234 | else: |
5bb322e2 | 235 | print("Bad register parse: ", regtype, regid, toss, numregs) |
793958c9 | 236 | else: |
5bb322e2 ML |
237 | print("Bad register parse: ", regtype, regid, toss, numregs) |
238 | ||
793958c9 | 239 | |
5bb322e2 ML |
240 | def genptr_decl_imm(f, immlett): |
241 | if immlett.isupper(): | |
793958c9 TS |
242 | i = 1 |
243 | else: | |
244 | i = 0 | |
cd6c4edf | 245 | f.write(f" int {hex_common.imm_name(immlett)} = insn->immed[{i}];\n") |
793958c9 | 246 | |
5bb322e2 | 247 | |
ccd9eec8 | 248 | def genptr_src_read(f, tag, regtype, regid): |
5bb322e2 ML |
249 | if regtype == "R": |
250 | if regid in {"ss", "tt", "xx", "yy"}: | |
251 | f.write( | |
252 | f" tcg_gen_concat_i32_i64({regtype}{regid}V, " | |
253 | f"hex_gpr[{regtype}{regid}N],\n" | |
254 | ) | |
255 | f.write( | |
256 | f" hex_gpr[{regtype}" | |
257 | f"{regid}N + 1]);\n" | |
258 | ) | |
259 | elif regid in {"x", "y"}: | |
e28b77a6 TS |
260 | ## For read/write registers, we need to get the original value into |
261 | ## the result TCGv. For conditional instructions, this is done in | |
262 | ## gen_start_packet. For unconditional instructions, we do it here. | |
5bb322e2 ML |
263 | if "A_CONDEXEC" not in hex_common.attribdict[tag]: |
264 | f.write( | |
265 | f" tcg_gen_mov_tl({regtype}{regid}V, " | |
266 | f"hex_gpr[{regtype}{regid}N]);\n" | |
267 | ) | |
268 | elif regid not in {"s", "t", "u", "v"}: | |
793958c9 | 269 | print("Bad register parse: ", regtype, regid) |
5bb322e2 ML |
270 | elif regtype == "P": |
271 | if regid == "x": | |
272 | f.write( | |
273 | f" tcg_gen_mov_tl({regtype}{regid}V, " | |
274 | f"hex_pred[{regtype}{regid}N]);\n" | |
275 | ) | |
276 | elif regid not in {"s", "t", "u", "v"}: | |
793958c9 | 277 | print("Bad register parse: ", regtype, regid) |
5bb322e2 ML |
278 | elif regtype == "C": |
279 | if regid == "ss": | |
280 | f.write( | |
281 | f" gen_read_ctrl_reg_pair(ctx, {regtype}{regid}N, " | |
282 | f"{regtype}{regid}V);\n" | |
283 | ) | |
284 | elif regid == "s": | |
285 | f.write( | |
286 | f" gen_read_ctrl_reg(ctx, {regtype}{regid}N, " | |
287 | f"{regtype}{regid}V);\n" | |
288 | ) | |
793958c9 TS |
289 | else: |
290 | print("Bad register parse: ", regtype, regid) | |
5bb322e2 ML |
291 | elif regtype == "M": |
292 | if regid != "u": | |
793958c9 | 293 | print("Bad register parse: ", regtype, regid) |
5bb322e2 ML |
294 | elif regtype == "V": |
295 | if regid in {"uu", "vv", "xx"}: | |
cd6c4edf ML |
296 | f.write(f" tcg_gen_gvec_mov(MO_64, {regtype}{regid}V_off,\n") |
297 | f.write(f" vreg_src_off(ctx, {regtype}{regid}N),\n") | |
ccd9eec8 TS |
298 | f.write(" sizeof(MMVector), sizeof(MMVector));\n") |
299 | f.write(" tcg_gen_gvec_mov(MO_64,\n") | |
cd6c4edf ML |
300 | f.write(f" {regtype}{regid}V_off + sizeof(MMVector),\n") |
301 | f.write(f" vreg_src_off(ctx, {regtype}{regid}N ^ 1),\n") | |
ccd9eec8 | 302 | f.write(" sizeof(MMVector), sizeof(MMVector));\n") |
5bb322e2 ML |
303 | elif regid in {"s", "u", "v", "w"}: |
304 | if not hex_common.skip_qemu_helper(tag): | |
305 | f.write( | |
306 | f" tcg_gen_addi_ptr({regtype}{regid}V, cpu_env, " | |
307 | f"{regtype}{regid}V_off);\n" | |
308 | ) | |
309 | elif regid in {"x", "y"}: | |
cd6c4edf ML |
310 | f.write(f" tcg_gen_gvec_mov(MO_64, {regtype}{regid}V_off,\n") |
311 | f.write(f" vreg_src_off(ctx, {regtype}{regid}N),\n") | |
ccd9eec8 | 312 | f.write(" sizeof(MMVector), sizeof(MMVector));\n") |
ccd9eec8 TS |
313 | else: |
314 | print("Bad register parse: ", regtype, regid) | |
5bb322e2 ML |
315 | elif regtype == "Q": |
316 | if regid in {"s", "t", "u", "v"}: | |
317 | if not hex_common.skip_qemu_helper(tag): | |
318 | f.write( | |
319 | f" tcg_gen_addi_ptr({regtype}{regid}V, cpu_env, " | |
320 | f"{regtype}{regid}V_off);\n" | |
321 | ) | |
322 | elif regid in {"x"}: | |
cd6c4edf | 323 | f.write(f" tcg_gen_gvec_mov(MO_64, {regtype}{regid}V_off,\n") |
5bb322e2 ML |
324 | f.write( |
325 | f" offsetof(CPUHexagonState, " f"QRegs[{regtype}{regid}N]),\n" | |
326 | ) | |
ccd9eec8 TS |
327 | f.write(" sizeof(MMQReg), sizeof(MMQReg));\n") |
328 | else: | |
329 | print("Bad register parse: ", regtype, regid) | |
793958c9 TS |
330 | else: |
331 | print("Bad register parse: ", regtype, regid) | |
332 | ||
5bb322e2 ML |
333 | |
334 | def genptr_src_read_new(f, regtype, regid): | |
335 | if regtype == "N": | |
336 | if regid not in {"s", "t"}: | |
793958c9 | 337 | print("Bad register parse: ", regtype, regid) |
5bb322e2 ML |
338 | elif regtype == "P": |
339 | if regid not in {"t", "u", "v"}: | |
793958c9 | 340 | print("Bad register parse: ", regtype, regid) |
5bb322e2 ML |
341 | elif regtype == "O": |
342 | if regid != "s": | |
ccd9eec8 | 343 | print("Bad register parse: ", regtype, regid) |
793958c9 TS |
344 | else: |
345 | print("Bad register parse: ", regtype, regid) | |
346 | ||
5bb322e2 ML |
347 | |
348 | def genptr_src_read_opn(f, regtype, regid, tag): | |
349 | if hex_common.is_pair(regid): | |
ccd9eec8 | 350 | genptr_src_read(f, tag, regtype, regid) |
5bb322e2 | 351 | elif hex_common.is_single(regid): |
793958c9 | 352 | if hex_common.is_old_val(regtype, regid, tag): |
ccd9eec8 | 353 | genptr_src_read(f, tag, regtype, regid) |
793958c9 | 354 | elif hex_common.is_new_val(regtype, regid, tag): |
5bb322e2 | 355 | genptr_src_read_new(f, regtype, regid) |
793958c9 | 356 | else: |
5bb322e2 | 357 | print("Bad register parse: ", regtype, regid, toss, numregs) |
793958c9 | 358 | else: |
5bb322e2 ML |
359 | print("Bad register parse: ", regtype, regid, toss, numregs) |
360 | ||
793958c9 TS |
361 | |
362 | def gen_helper_call_opn(f, tag, regtype, regid, toss, numregs, i): | |
5bb322e2 ML |
363 | if i > 0: |
364 | f.write(", ") | |
365 | if hex_common.is_pair(regid): | |
cd6c4edf | 366 | f.write(f"{regtype}{regid}V") |
5bb322e2 | 367 | elif hex_common.is_single(regid): |
793958c9 | 368 | if hex_common.is_old_val(regtype, regid, tag): |
cd6c4edf | 369 | f.write(f"{regtype}{regid}V") |
793958c9 | 370 | elif hex_common.is_new_val(regtype, regid, tag): |
cd6c4edf | 371 | f.write(f"{regtype}{regid}N") |
793958c9 | 372 | else: |
5bb322e2 | 373 | print("Bad register parse: ", regtype, regid, toss, numregs) |
793958c9 | 374 | else: |
5bb322e2 | 375 | print("Bad register parse: ", regtype, regid, toss, numregs) |
793958c9 | 376 | |
793958c9 | 377 | |
5bb322e2 ML |
378 | def gen_helper_decl_imm(f, immlett): |
379 | f.write( | |
380 | f" TCGv tcgv_{hex_common.imm_name(immlett)} = " | |
381 | f"tcg_constant_tl({hex_common.imm_name(immlett)});\n" | |
382 | ) | |
383 | ||
384 | ||
385 | def gen_helper_call_imm(f, immlett): | |
cd6c4edf | 386 | f.write(f", tcgv_{hex_common.imm_name(immlett)}") |
793958c9 | 387 | |
5bb322e2 | 388 | |
793958c9 | 389 | def genptr_dst_write_pair(f, tag, regtype, regid): |
07540a28 TS |
390 | f.write(f" gen_log_reg_write_pair(ctx, {regtype}{regid}N, " |
391 | f"{regtype}{regid}V);\n") | |
5bb322e2 | 392 | |
793958c9 TS |
393 | |
394 | def genptr_dst_write(f, tag, regtype, regid): | |
5bb322e2 ML |
395 | if regtype == "R": |
396 | if regid in {"dd", "xx", "yy"}: | |
793958c9 | 397 | genptr_dst_write_pair(f, tag, regtype, regid) |
5bb322e2 ML |
398 | elif regid in {"d", "e", "x", "y"}: |
399 | f.write( | |
07540a28 TS |
400 | f" gen_log_reg_write(ctx, {regtype}{regid}N, " |
401 | f"{regtype}{regid}V);\n" | |
5bb322e2 | 402 | ) |
793958c9 TS |
403 | else: |
404 | print("Bad register parse: ", regtype, regid) | |
5bb322e2 ML |
405 | elif regtype == "P": |
406 | if regid in {"d", "e", "x"}: | |
407 | f.write( | |
408 | f" gen_log_pred_write(ctx, {regtype}{regid}N, " | |
409 | f"{regtype}{regid}V);\n" | |
410 | ) | |
793958c9 TS |
411 | else: |
412 | print("Bad register parse: ", regtype, regid) | |
5bb322e2 ML |
413 | elif regtype == "C": |
414 | if regid == "dd": | |
415 | f.write( | |
416 | f" gen_write_ctrl_reg_pair(ctx, {regtype}{regid}N, " | |
417 | f"{regtype}{regid}V);\n" | |
418 | ) | |
419 | elif regid == "d": | |
420 | f.write( | |
421 | f" gen_write_ctrl_reg(ctx, {regtype}{regid}N, " | |
422 | f"{regtype}{regid}V);\n" | |
423 | ) | |
793958c9 TS |
424 | else: |
425 | print("Bad register parse: ", regtype, regid) | |
426 | else: | |
427 | print("Bad register parse: ", regtype, regid) | |
428 | ||
5bb322e2 | 429 | |
ccd9eec8 | 430 | def genptr_dst_write_ext(f, tag, regtype, regid, newv="EXT_DFL"): |
5bb322e2 ML |
431 | if regtype == "V": |
432 | if regid in {"xx"}: | |
433 | f.write( | |
434 | f" gen_log_vreg_write_pair(ctx, {regtype}{regid}V_off, " | |
435 | f"{regtype}{regid}N, {newv});\n" | |
436 | ) | |
437 | elif regid in {"y"}: | |
438 | f.write( | |
439 | f" gen_log_vreg_write(ctx, {regtype}{regid}V_off, " | |
440 | f"{regtype}{regid}N, {newv});\n" | |
441 | ) | |
442 | elif regid not in {"dd", "d", "x"}: | |
ccd9eec8 | 443 | print("Bad register parse: ", regtype, regid) |
5bb322e2 ML |
444 | elif regtype == "Q": |
445 | if regid not in {"d", "e", "x"}: | |
ccd9eec8 TS |
446 | print("Bad register parse: ", regtype, regid) |
447 | else: | |
448 | print("Bad register parse: ", regtype, regid) | |
449 | ||
5bb322e2 ML |
450 | |
451 | def genptr_dst_write_opn(f, regtype, regid, tag): | |
452 | if hex_common.is_pair(regid): | |
453 | if hex_common.is_hvx_reg(regtype): | |
454 | if hex_common.is_tmp_result(tag): | |
ccd9eec8 TS |
455 | genptr_dst_write_ext(f, tag, regtype, regid, "EXT_TMP") |
456 | else: | |
457 | genptr_dst_write_ext(f, tag, regtype, regid) | |
458 | else: | |
459 | genptr_dst_write(f, tag, regtype, regid) | |
5bb322e2 ML |
460 | elif hex_common.is_single(regid): |
461 | if hex_common.is_hvx_reg(regtype): | |
462 | if hex_common.is_new_result(tag): | |
ccd9eec8 | 463 | genptr_dst_write_ext(f, tag, regtype, regid, "EXT_NEW") |
5bb322e2 | 464 | elif hex_common.is_tmp_result(tag): |
ccd9eec8 TS |
465 | genptr_dst_write_ext(f, tag, regtype, regid, "EXT_TMP") |
466 | else: | |
467 | genptr_dst_write_ext(f, tag, regtype, regid, "EXT_DFL") | |
468 | else: | |
469 | genptr_dst_write(f, tag, regtype, regid) | |
793958c9 | 470 | else: |
5bb322e2 ML |
471 | print("Bad register parse: ", regtype, regid, toss, numregs) |
472 | ||
793958c9 TS |
473 | |
474 | ## | |
475 | ## Generate the TCG code to call the helper | |
476 | ## For A2_add: Rd32=add(Rs32,Rt32), { RdV=RsV+RtV;} | |
477 | ## We produce: | |
1e536334 | 478 | ## static void generate_A2_add(DisasContext *ctx) |
e28b77a6 TS |
479 | ## { |
480 | ## Insn *insn __attribute__((unused)) = ctx->insn; | |
481 | ## const int RdN = insn->regno[0]; | |
482 | ## TCGv RdV = get_result_gpr(ctx, RdN); | |
483 | ## TCGv RsV = hex_gpr[insn->regno[1]]; | |
484 | ## TCGv RtV = hex_gpr[insn->regno[2]]; | |
485 | ## <GEN> | |
07540a28 | 486 | ## gen_log_reg_write(ctx, RdN, RdV); |
e28b77a6 | 487 | ## } |
793958c9 TS |
488 | ## |
489 | ## where <GEN> depends on hex_common.skip_qemu_helper(tag) | |
490 | ## if hex_common.skip_qemu_helper(tag) is True | |
491 | ## <GEN> is fGEN_TCG_A2_add({ RdV=RsV+RtV;}); | |
492 | ## if hex_common.skip_qemu_helper(tag) is False | |
493 | ## <GEN> is gen_helper_A2_add(RdV, cpu_env, RsV, RtV); | |
494 | ## | |
495 | def gen_tcg_func(f, tag, regs, imms): | |
cd6c4edf | 496 | f.write(f"static void generate_{tag}(DisasContext *ctx)\n") |
5bb322e2 | 497 | f.write("{\n") |
1e536334 TS |
498 | |
499 | f.write(" Insn *insn __attribute__((unused)) = ctx->insn;\n") | |
500 | ||
5bb322e2 ML |
501 | if hex_common.need_ea(tag): |
502 | gen_decl_ea_tcg(f, tag) | |
503 | i = 0 | |
793958c9 | 504 | ## Declare all the operands (regs and immediates) |
5bb322e2 | 505 | for regtype, regid, toss, numregs in regs: |
793958c9 TS |
506 | genptr_decl_opn(f, tag, regtype, regid, toss, numregs, i) |
507 | i += 1 | |
5bb322e2 ML |
508 | for immlett, bits, immshift in imms: |
509 | genptr_decl_imm(f, immlett) | |
793958c9 | 510 | |
5bb322e2 ML |
511 | if "A_PRIV" in hex_common.attribdict[tag]: |
512 | f.write(" fCHECKFORPRIV();\n") | |
513 | if "A_GUEST" in hex_common.attribdict[tag]: | |
514 | f.write(" fCHECKFORGUEST();\n") | |
793958c9 TS |
515 | |
516 | ## Read all the inputs | |
5bb322e2 ML |
517 | for regtype, regid, toss, numregs in regs: |
518 | if hex_common.is_read(regid): | |
519 | genptr_src_read_opn(f, regtype, regid, tag) | |
793958c9 | 520 | |
e71fdc4f ADF |
521 | if hex_common.is_idef_parser_enabled(tag): |
522 | declared = [] | |
523 | ## Handle registers | |
5bb322e2 ML |
524 | for regtype, regid, toss, numregs in regs: |
525 | if hex_common.is_pair(regid) or ( | |
526 | hex_common.is_single(regid) | |
527 | and hex_common.is_old_val(regtype, regid, tag) | |
528 | ): | |
cd6c4edf | 529 | declared.append(f"{regtype}{regid}V") |
e71fdc4f | 530 | if regtype == "M": |
cd6c4edf | 531 | declared.append(f"{regtype}{regid}N") |
e71fdc4f | 532 | elif hex_common.is_new_val(regtype, regid, tag): |
cd6c4edf | 533 | declared.append(f"{regtype}{regid}N") |
e71fdc4f | 534 | else: |
5bb322e2 | 535 | print("Bad register parse: ", regtype, regid, toss, numregs) |
e71fdc4f ADF |
536 | |
537 | ## Handle immediates | |
5bb322e2 | 538 | for immlett, bits, immshift in imms: |
e71fdc4f ADF |
539 | declared.append(hex_common.imm_name(immlett)) |
540 | ||
541 | arguments = ", ".join(["ctx", "ctx->insn", "ctx->pkt"] + declared) | |
cd6c4edf | 542 | f.write(f" emit_{tag}({arguments});\n") |
e71fdc4f | 543 | |
5bb322e2 | 544 | elif hex_common.skip_qemu_helper(tag): |
cd6c4edf | 545 | f.write(f" fGEN_TCG_{tag}({hex_common.semdict[tag]});\n") |
793958c9 TS |
546 | else: |
547 | ## Generate the call to the helper | |
5bb322e2 ML |
548 | for immlett, bits, immshift in imms: |
549 | gen_helper_decl_imm(f, immlett) | |
fb67c2bf TS |
550 | if hex_common.need_pkt_has_multi_cof(tag): |
551 | f.write(" TCGv pkt_has_multi_cof = ") | |
552 | f.write("tcg_constant_tl(ctx->pkt->pkt_has_multi_cof);\n") | |
d54c5615 TS |
553 | if hex_common.need_pkt_need_commit(tag): |
554 | f.write(" TCGv pkt_need_commit = ") | |
555 | f.write("tcg_constant_tl(ctx->need_commit);\n") | |
793958c9 | 556 | if hex_common.need_part1(tag): |
f448397a | 557 | f.write(" TCGv part1 = tcg_constant_tl(insn->part1);\n") |
793958c9 | 558 | if hex_common.need_slot(tag): |
23803bbe | 559 | f.write(" TCGv slot = tcg_constant_tl(insn->slot);\n") |
40085901 TS |
560 | if hex_common.need_PC(tag): |
561 | f.write(" TCGv PC = tcg_constant_tl(ctx->pkt->pc);\n") | |
613653e5 TS |
562 | if hex_common.helper_needs_next_PC(tag): |
563 | f.write(" TCGv next_PC = tcg_constant_tl(ctx->next_PC);\n") | |
cd6c4edf | 564 | f.write(f" gen_helper_{tag}(") |
5bb322e2 | 565 | i = 0 |
793958c9 | 566 | ## If there is a scalar result, it is the return type |
5bb322e2 ML |
567 | for regtype, regid, toss, numregs in regs: |
568 | if hex_common.is_written(regid): | |
569 | if hex_common.is_hvx_reg(regtype): | |
ccd9eec8 | 570 | continue |
793958c9 TS |
571 | gen_helper_call_opn(f, tag, regtype, regid, toss, numregs, i) |
572 | i += 1 | |
5bb322e2 ML |
573 | if i > 0: |
574 | f.write(", ") | |
793958c9 | 575 | f.write("cpu_env") |
5bb322e2 | 576 | i = 1 |
e28b77a6 | 577 | ## For conditional instructions, we pass in the destination register |
5bb322e2 | 578 | if "A_CONDEXEC" in hex_common.attribdict[tag]: |
e28b77a6 | 579 | for regtype, regid, toss, numregs in regs: |
5bb322e2 ML |
580 | if hex_common.is_writeonly(regid) and not hex_common.is_hvx_reg( |
581 | regtype | |
582 | ): | |
583 | gen_helper_call_opn(f, tag, regtype, regid, toss, numregs, i) | |
e28b77a6 | 584 | i += 1 |
5bb322e2 ML |
585 | for regtype, regid, toss, numregs in regs: |
586 | if hex_common.is_written(regid): | |
587 | if not hex_common.is_hvx_reg(regtype): | |
ccd9eec8 TS |
588 | continue |
589 | gen_helper_call_opn(f, tag, regtype, regid, toss, numregs, i) | |
590 | i += 1 | |
5bb322e2 ML |
591 | for regtype, regid, toss, numregs in regs: |
592 | if hex_common.is_read(regid): | |
593 | if hex_common.is_hvx_reg(regtype) and hex_common.is_readwrite(regid): | |
ccd9eec8 | 594 | continue |
793958c9 TS |
595 | gen_helper_call_opn(f, tag, regtype, regid, toss, numregs, i) |
596 | i += 1 | |
5bb322e2 ML |
597 | for immlett, bits, immshift in imms: |
598 | gen_helper_call_imm(f, immlett) | |
793958c9 | 599 | |
fb67c2bf TS |
600 | if hex_common.need_pkt_has_multi_cof(tag): |
601 | f.write(", pkt_has_multi_cof") | |
d54c5615 TS |
602 | if hex_common.need_pkt_need_commit(tag): |
603 | f.write(", pkt_need_commit") | |
5bb322e2 ML |
604 | if hex_common.need_PC(tag): |
605 | f.write(", PC") | |
606 | if hex_common.helper_needs_next_PC(tag): | |
607 | f.write(", next_PC") | |
608 | if hex_common.need_slot(tag): | |
609 | f.write(", slot") | |
610 | if hex_common.need_part1(tag): | |
611 | f.write(", part1") | |
793958c9 | 612 | f.write(");\n") |
793958c9 TS |
613 | |
614 | ## Write all the outputs | |
5bb322e2 ML |
615 | for regtype, regid, toss, numregs in regs: |
616 | if hex_common.is_written(regid): | |
617 | genptr_dst_write_opn(f, regtype, regid, tag) | |
793958c9 | 618 | |
793958c9 TS |
619 | f.write("}\n\n") |
620 | ||
5bb322e2 | 621 | |
793958c9 TS |
622 | def gen_def_tcg_func(f, tag, tagregs, tagimms): |
623 | regs = tagregs[tag] | |
624 | imms = tagimms[tag] | |
625 | ||
626 | gen_tcg_func(f, tag, regs, imms) | |
627 | ||
5bb322e2 | 628 | |
793958c9 TS |
629 | def main(): |
630 | hex_common.read_semantics_file(sys.argv[1]) | |
631 | hex_common.read_attribs_file(sys.argv[2]) | |
632 | hex_common.read_overrides_file(sys.argv[3]) | |
d51bcabe | 633 | hex_common.read_overrides_file(sys.argv[4]) |
793958c9 | 634 | hex_common.calculate_attribs() |
e71fdc4f ADF |
635 | ## Whether or not idef-parser is enabled is |
636 | ## determined by the number of arguments to | |
637 | ## this script: | |
638 | ## | |
639 | ## 5 args. -> not enabled, | |
640 | ## 6 args. -> idef-parser enabled. | |
641 | ## | |
642 | ## The 6:th arg. then holds a list of the successfully | |
643 | ## parsed instructions. | |
644 | is_idef_parser_enabled = len(sys.argv) > 6 | |
645 | if is_idef_parser_enabled: | |
646 | hex_common.read_idef_parser_enabled_file(sys.argv[5]) | |
793958c9 TS |
647 | tagregs = hex_common.get_tagregs() |
648 | tagimms = hex_common.get_tagimms() | |
649 | ||
e71fdc4f | 650 | output_file = sys.argv[-1] |
5bb322e2 | 651 | with open(output_file, "w") as f: |
793958c9 TS |
652 | f.write("#ifndef HEXAGON_TCG_FUNCS_H\n") |
653 | f.write("#define HEXAGON_TCG_FUNCS_H\n\n") | |
e71fdc4f | 654 | if is_idef_parser_enabled: |
5bb322e2 | 655 | f.write('#include "idef-generated-emitter.h.inc"\n\n') |
793958c9 TS |
656 | |
657 | for tag in hex_common.tags: | |
658 | ## Skip the priv instructions | |
5bb322e2 | 659 | if "A_PRIV" in hex_common.attribdict[tag]: |
793958c9 TS |
660 | continue |
661 | ## Skip the guest instructions | |
5bb322e2 | 662 | if "A_GUEST" in hex_common.attribdict[tag]: |
793958c9 TS |
663 | continue |
664 | ## Skip the diag instructions | |
5bb322e2 | 665 | if tag == "Y6_diag": |
793958c9 | 666 | continue |
5bb322e2 | 667 | if tag == "Y6_diag0": |
793958c9 | 668 | continue |
5bb322e2 | 669 | if tag == "Y6_diag1": |
793958c9 TS |
670 | continue |
671 | ||
672 | gen_def_tcg_func(f, tag, tagregs, tagimms) | |
673 | ||
674 | f.write("#endif /* HEXAGON_TCG_FUNCS_H */\n") | |
675 | ||
5bb322e2 | 676 | |
793958c9 TS |
677 | if __name__ == "__main__": |
678 | main() |