]> git.proxmox.com Git - mirror_qemu.git/blame - target/hexagon/translate.c
tcg: Split helper-gen.h
[mirror_qemu.git] / target / hexagon / translate.c
CommitLineData
8b453a2b 1/*
10849c26 2 * Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
8b453a2b
TS
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18#define QEMU_GENERATE
19#include "qemu/osdep.h"
20#include "cpu.h"
21#include "tcg/tcg-op.h"
a82dd548 22#include "tcg/tcg-op-gvec.h"
13e27d1f 23#include "exec/helper-gen.h"
8b453a2b
TS
24#include "exec/cpu_ldst.h"
25#include "exec/log.h"
26#include "internal.h"
27#include "attribs.h"
28#include "insn.h"
29#include "decode.h"
30#include "translate.h"
d54c5615 31#include "genptr.h"
8b453a2b
TS
32#include "printinsn.h"
33
d53106c9
RH
34#define HELPER_H "helper.h"
35#include "exec/helper-info.c.inc"
36#undef HELPER_H
37
10849c26
TS
38#include "analyze_funcs_generated.c.inc"
39
40typedef void (*AnalyzeInsn)(DisasContext *ctx);
41static const AnalyzeInsn opcode_analyze[XX_LAST_OPCODE] = {
42#define OPCODE(X) [X] = analyze_##X
43#include "opcodes_def_generated.h.inc"
44#undef OPCODE
45};
46
8b453a2b
TS
47TCGv hex_gpr[TOTAL_PER_THREAD_REGS];
48TCGv hex_pred[NUM_PREGS];
8b453a2b 49TCGv hex_slot_cancelled;
6aa4f1d1 50TCGv hex_new_value_usr;
8b453a2b 51TCGv hex_reg_written[TOTAL_PER_THREAD_REGS];
8b453a2b
TS
52TCGv hex_store_addr[STORES_MAX];
53TCGv hex_store_width[STORES_MAX];
54TCGv hex_store_val32[STORES_MAX];
55TCGv_i64 hex_store_val64[STORES_MAX];
8b453a2b
TS
56TCGv hex_llsc_addr;
57TCGv hex_llsc_val;
58TCGv_i64 hex_llsc_val_i64;
a82dd548
TS
59TCGv hex_vstore_addr[VSTORES_MAX];
60TCGv hex_vstore_size[VSTORES_MAX];
61TCGv hex_vstore_pending[VSTORES_MAX];
8b453a2b
TS
62
63static const char * const hexagon_prednames[] = {
64 "p0", "p1", "p2", "p3"
65};
66
a82dd548
TS
67intptr_t ctx_future_vreg_off(DisasContext *ctx, int regnum,
68 int num, bool alloc_ok)
69{
70 intptr_t offset;
71
b8552985
TS
72 if (!ctx->need_commit) {
73 return offsetof(CPUHexagonState, VRegs[regnum]);
74 }
75
a82dd548
TS
76 /* See if it is already allocated */
77 for (int i = 0; i < ctx->future_vregs_idx; i++) {
78 if (ctx->future_vregs_num[i] == regnum) {
79 return offsetof(CPUHexagonState, future_VRegs[i]);
80 }
81 }
82
83 g_assert(alloc_ok);
84 offset = offsetof(CPUHexagonState, future_VRegs[ctx->future_vregs_idx]);
85 for (int i = 0; i < num; i++) {
86 ctx->future_vregs_num[ctx->future_vregs_idx + i] = regnum++;
87 }
88 ctx->future_vregs_idx += num;
89 g_assert(ctx->future_vregs_idx <= VECTOR_TEMPS_MAX);
90 return offset;
91}
92
93intptr_t ctx_tmp_vreg_off(DisasContext *ctx, int regnum,
94 int num, bool alloc_ok)
95{
96 intptr_t offset;
97
98 /* See if it is already allocated */
99 for (int i = 0; i < ctx->tmp_vregs_idx; i++) {
100 if (ctx->tmp_vregs_num[i] == regnum) {
101 return offsetof(CPUHexagonState, tmp_VRegs[i]);
102 }
103 }
104
105 g_assert(alloc_ok);
106 offset = offsetof(CPUHexagonState, tmp_VRegs[ctx->tmp_vregs_idx]);
107 for (int i = 0; i < num; i++) {
108 ctx->tmp_vregs_num[ctx->tmp_vregs_idx + i] = regnum++;
109 }
110 ctx->tmp_vregs_idx += num;
111 g_assert(ctx->tmp_vregs_idx <= VECTOR_TEMPS_MAX);
112 return offset;
113}
114
743debbc 115static void gen_exception_raw(int excp)
8b453a2b 116{
23803bbe 117 gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp));
8b453a2b
TS
118}
119
743debbc
TS
120static void gen_exec_counters(DisasContext *ctx)
121{
122 tcg_gen_addi_tl(hex_gpr[HEX_REG_QEMU_PKT_CNT],
123 hex_gpr[HEX_REG_QEMU_PKT_CNT], ctx->num_packets);
124 tcg_gen_addi_tl(hex_gpr[HEX_REG_QEMU_INSN_CNT],
125 hex_gpr[HEX_REG_QEMU_INSN_CNT], ctx->num_insns);
a82dd548
TS
126 tcg_gen_addi_tl(hex_gpr[HEX_REG_QEMU_HVX_CNT],
127 hex_gpr[HEX_REG_QEMU_HVX_CNT], ctx->num_hvx_insns);
743debbc
TS
128}
129
1b9a7f2a
TS
130static bool use_goto_tb(DisasContext *ctx, target_ulong dest)
131{
132 return translator_use_goto_tb(&ctx->base, dest);
133}
134
bee1fc56
MTB
135static void gen_goto_tb(DisasContext *ctx, int idx, target_ulong dest, bool
136 move_to_pc)
1b9a7f2a
TS
137{
138 if (use_goto_tb(ctx, dest)) {
139 tcg_gen_goto_tb(idx);
bee1fc56
MTB
140 if (move_to_pc) {
141 tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], dest);
142 }
1b9a7f2a
TS
143 tcg_gen_exit_tb(ctx->base.tb, idx);
144 } else {
bee1fc56
MTB
145 if (move_to_pc) {
146 tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], dest);
147 }
1b9a7f2a
TS
148 tcg_gen_lookup_and_goto_ptr();
149 }
150}
151
743debbc 152static void gen_end_tb(DisasContext *ctx)
8b453a2b 153{
564b2040
TS
154 Packet *pkt = ctx->pkt;
155
743debbc 156 gen_exec_counters(ctx);
1b9a7f2a
TS
157
158 if (ctx->branch_cond != TCG_COND_NEVER) {
159 if (ctx->branch_cond != TCG_COND_ALWAYS) {
160 TCGLabel *skip = gen_new_label();
0fc56c43 161 tcg_gen_brcondi_tl(ctx->branch_cond, ctx->branch_taken, 0, skip);
bee1fc56 162 gen_goto_tb(ctx, 0, ctx->branch_dest, true);
1b9a7f2a 163 gen_set_label(skip);
bee1fc56 164 gen_goto_tb(ctx, 1, ctx->next_PC, false);
1b9a7f2a 165 } else {
bee1fc56 166 gen_goto_tb(ctx, 0, ctx->branch_dest, true);
1b9a7f2a 167 }
564b2040
TS
168 } else if (ctx->is_tight_loop &&
169 pkt->insn[pkt->num_insns - 1].opcode == J2_endloop0) {
170 /*
171 * When we're in a tight loop, we defer the endloop0 processing
172 * to take advantage of direct block chaining
173 */
174 TCGLabel *skip = gen_new_label();
175 tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC0], 1, skip);
176 tcg_gen_subi_tl(hex_gpr[HEX_REG_LC0], hex_gpr[HEX_REG_LC0], 1);
bee1fc56 177 gen_goto_tb(ctx, 0, ctx->base.tb->pc, true);
564b2040 178 gen_set_label(skip);
bee1fc56 179 gen_goto_tb(ctx, 1, ctx->next_PC, false);
1b9a7f2a
TS
180 } else {
181 tcg_gen_lookup_and_goto_ptr();
182 }
183
743debbc
TS
184 ctx->base.is_jmp = DISAS_NORETURN;
185}
186
187static void gen_exception_end_tb(DisasContext *ctx, int excp)
188{
189 gen_exec_counters(ctx);
613653e5 190 tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], ctx->next_PC);
743debbc
TS
191 gen_exception_raw(excp);
192 ctx->base.is_jmp = DISAS_NORETURN;
193
8b453a2b
TS
194}
195
8b453a2b
TS
196#define PACKET_BUFFER_LEN 1028
197static void print_pkt(Packet *pkt)
198{
199 GString *buf = g_string_sized_new(PACKET_BUFFER_LEN);
200 snprint_a_pkt_debug(buf, pkt);
201 HEX_DEBUG_LOG("%s", buf->str);
202 g_string_free(buf, true);
203}
85580a65
TS
204#define HEX_DEBUG_PRINT_PKT(pkt) \
205 do { \
206 if (HEX_DEBUG) { \
207 print_pkt(pkt); \
208 } \
209 } while (0)
8b453a2b
TS
210
211static int read_packet_words(CPUHexagonState *env, DisasContext *ctx,
212 uint32_t words[])
213{
214 bool found_end = false;
215 int nwords, max_words;
216
217 memset(words, 0, PACKET_WORDS_MAX * sizeof(uint32_t));
218 for (nwords = 0; !found_end && nwords < PACKET_WORDS_MAX; nwords++) {
a27c100c 219 words[nwords] =
4e116893
IL
220 translator_ldl(env, &ctx->base,
221 ctx->base.pc_next + nwords * sizeof(uint32_t));
8b453a2b
TS
222 found_end = is_packet_end(words[nwords]);
223 }
224 if (!found_end) {
225 /* Read too many words without finding the end */
226 return 0;
227 }
228
229 /* Check for page boundary crossing */
230 max_words = -(ctx->base.pc_next | TARGET_PAGE_MASK) / sizeof(uint32_t);
231 if (nwords > max_words) {
232 /* We can only cross a page boundary at the beginning of a TB */
233 g_assert(ctx->base.num_insns == 1);
234 }
235
236 HEX_DEBUG_LOG("decode_packet: pc = 0x%x\n", ctx->base.pc_next);
237 HEX_DEBUG_LOG(" words = { ");
238 for (int i = 0; i < nwords; i++) {
239 HEX_DEBUG_LOG("0x%x, ", words[i]);
240 }
241 HEX_DEBUG_LOG("}\n");
242
243 return nwords;
244}
245
d54c5615 246static bool check_for_attrib(Packet *pkt, int attrib)
8b453a2b
TS
247{
248 for (int i = 0; i < pkt->num_insns; i++) {
249 if (GET_ATTRIB(pkt->insn[i].opcode, attrib)) {
250 return true;
251 }
252 }
253 return false;
254}
255
8b453a2b
TS
256static bool need_slot_cancelled(Packet *pkt)
257{
c2b33d0b 258 /* We only need slot_cancelled for conditional store instructions */
7b84fd04
TS
259 for (int i = 0; i < pkt->num_insns; i++) {
260 uint16_t opcode = pkt->insn[i].opcode;
261 if (GET_ATTRIB(opcode, A_CONDEXEC) &&
c2b33d0b 262 GET_ATTRIB(opcode, A_SCALAR_STORE)) {
7b84fd04
TS
263 return true;
264 }
265 }
266 return false;
8b453a2b
TS
267}
268
613653e5
TS
269static bool need_next_PC(DisasContext *ctx)
270{
271 Packet *pkt = ctx->pkt;
272
273 /* Check for conditional control flow or HW loop end */
274 for (int i = 0; i < pkt->num_insns; i++) {
275 uint16_t opcode = pkt->insn[i].opcode;
276 if (GET_ATTRIB(opcode, A_CONDEXEC) && GET_ATTRIB(opcode, A_COF)) {
277 return true;
278 }
279 if (GET_ATTRIB(opcode, A_HWLOOP0_END) ||
280 GET_ATTRIB(opcode, A_HWLOOP1_END)) {
281 return true;
282 }
283 }
284 return false;
285}
286
10849c26
TS
287/*
288 * The opcode_analyze functions mark most of the writes in a packet
289 * However, there are some implicit writes marked as attributes
290 * of the applicable instructions.
291 */
292static void mark_implicit_reg_write(DisasContext *ctx, int attrib, int rnum)
293{
294 uint16_t opcode = ctx->insn->opcode;
295 if (GET_ATTRIB(opcode, attrib)) {
296 /*
297 * USR is used to set overflow and FP exceptions,
298 * so treat it as conditional
299 */
300 bool is_predicated = GET_ATTRIB(opcode, A_CONDEXEC) ||
301 rnum == HEX_REG_USR;
302
303 /* LC0/LC1 is conditionally written by endloop instructions */
304 if ((rnum == HEX_REG_LC0 || rnum == HEX_REG_LC1) &&
305 (opcode == J2_endloop0 ||
306 opcode == J2_endloop1 ||
307 opcode == J2_endloop01)) {
308 is_predicated = true;
309 }
310
311 ctx_log_reg_write(ctx, rnum, is_predicated);
312 }
313}
314
315static void mark_implicit_reg_writes(DisasContext *ctx)
316{
317 mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_FP, HEX_REG_FP);
318 mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_SP, HEX_REG_SP);
319 mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_LR, HEX_REG_LR);
320 mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_LC0, HEX_REG_LC0);
321 mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_SA0, HEX_REG_SA0);
322 mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_LC1, HEX_REG_LC1);
323 mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_SA1, HEX_REG_SA1);
324 mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_USR, HEX_REG_USR);
325 mark_implicit_reg_write(ctx, A_FPOP, HEX_REG_USR);
326}
327
328static void mark_implicit_pred_write(DisasContext *ctx, int attrib, int pnum)
329{
330 if (GET_ATTRIB(ctx->insn->opcode, attrib)) {
331 ctx_log_pred_write(ctx, pnum);
332 }
333}
334
335static void mark_implicit_pred_writes(DisasContext *ctx)
336{
337 mark_implicit_pred_write(ctx, A_IMPLICIT_WRITES_P0, 0);
338 mark_implicit_pred_write(ctx, A_IMPLICIT_WRITES_P1, 1);
339 mark_implicit_pred_write(ctx, A_IMPLICIT_WRITES_P2, 2);
340 mark_implicit_pred_write(ctx, A_IMPLICIT_WRITES_P3, 3);
341}
342
d54c5615
TS
343static bool pkt_raises_exception(Packet *pkt)
344{
345 if (check_for_attrib(pkt, A_LOAD) ||
346 check_for_attrib(pkt, A_STORE)) {
347 return true;
348 }
349 return false;
350}
351
352static bool need_commit(DisasContext *ctx)
353{
354 Packet *pkt = ctx->pkt;
355
356 /*
357 * If the short-circuit property is set to false, we'll always do the commit
358 */
359 if (!ctx->short_circuit) {
360 return true;
361 }
362
363 if (pkt_raises_exception(pkt)) {
364 return true;
365 }
366
367 /* Registers with immutability flags require new_value */
368 for (int i = 0; i < ctx->reg_log_idx; i++) {
369 int rnum = ctx->reg_log[i];
370 if (reg_immut_masks[rnum]) {
371 return true;
372 }
373 }
374
375 /* Floating point instructions are hard-coded to use new_value */
376 if (check_for_attrib(pkt, A_FPOP)) {
377 return true;
378 }
379
d05d5eeb
TS
380 if (pkt->num_insns == 1) {
381 if (pkt->pkt_has_hvx) {
382 /*
383 * The HVX instructions with generated helpers use
384 * pass-by-reference, so they need the read/write overlap
385 * check below.
386 * The HVX instructions with overrides are OK.
387 */
388 if (!ctx->has_hvx_helper) {
389 return false;
390 }
391 } else {
392 return false;
393 }
d54c5615
TS
394 }
395
396 /* Check for overlap between register reads and writes */
397 for (int i = 0; i < ctx->reg_log_idx; i++) {
398 int rnum = ctx->reg_log[i];
399 if (test_bit(rnum, ctx->regs_read)) {
400 return true;
401 }
402 }
403
455e169d
TS
404 /* Check for overlap between predicate reads and writes */
405 for (int i = 0; i < ctx->preg_log_idx; i++) {
406 int pnum = ctx->preg_log[i];
407 if (test_bit(pnum, ctx->pregs_read)) {
408 return true;
409 }
410 }
411
b8552985
TS
412 /* Check for overlap between HVX reads and writes */
413 for (int i = 0; i < ctx->vreg_log_idx; i++) {
414 int vnum = ctx->vreg_log[i];
415 if (test_bit(vnum, ctx->vregs_read)) {
416 return true;
417 }
418 }
419 if (!bitmap_empty(ctx->vregs_updated_tmp, NUM_VREGS)) {
420 int i = find_first_bit(ctx->vregs_updated_tmp, NUM_VREGS);
421 while (i < NUM_VREGS) {
422 if (test_bit(i, ctx->vregs_read)) {
423 return true;
424 }
425 i = find_next_bit(ctx->vregs_updated_tmp, NUM_VREGS, i + 1);
426 }
427 }
428 if (!bitmap_empty(ctx->vregs_select, NUM_VREGS)) {
429 int i = find_first_bit(ctx->vregs_select, NUM_VREGS);
430 while (i < NUM_VREGS) {
431 if (test_bit(i, ctx->vregs_read)) {
432 return true;
433 }
434 i = find_next_bit(ctx->vregs_select, NUM_VREGS, i + 1);
435 }
436 }
437
438 /* Check for overlap between HVX predicate reads and writes */
439 for (int i = 0; i < ctx->qreg_log_idx; i++) {
440 int qnum = ctx->qreg_log[i];
441 if (test_bit(qnum, ctx->qregs_read)) {
442 return true;
443 }
444 }
445
d54c5615
TS
446 return false;
447}
448
b9f0326b
TS
449static void mark_implicit_pred_read(DisasContext *ctx, int attrib, int pnum)
450{
451 if (GET_ATTRIB(ctx->insn->opcode, attrib)) {
452 ctx_log_pred_read(ctx, pnum);
453 }
454}
455
456static void mark_implicit_pred_reads(DisasContext *ctx)
457{
458 mark_implicit_pred_read(ctx, A_IMPLICIT_READS_P0, 0);
459 mark_implicit_pred_read(ctx, A_IMPLICIT_READS_P1, 1);
460 mark_implicit_pred_read(ctx, A_IMPLICIT_READS_P3, 2);
461 mark_implicit_pred_read(ctx, A_IMPLICIT_READS_P3, 3);
462}
463
10849c26
TS
464static void analyze_packet(DisasContext *ctx)
465{
466 Packet *pkt = ctx->pkt;
d05d5eeb 467 ctx->has_hvx_helper = false;
10849c26
TS
468 for (int i = 0; i < pkt->num_insns; i++) {
469 Insn *insn = &pkt->insn[i];
470 ctx->insn = insn;
471 if (opcode_analyze[insn->opcode]) {
472 opcode_analyze[insn->opcode](ctx);
473 }
474 mark_implicit_reg_writes(ctx);
475 mark_implicit_pred_writes(ctx);
b9f0326b 476 mark_implicit_pred_reads(ctx);
10849c26 477 }
d54c5615
TS
478
479 ctx->need_commit = need_commit(ctx);
10849c26
TS
480}
481
1e536334 482static void gen_start_packet(DisasContext *ctx)
8b453a2b 483{
1e536334 484 Packet *pkt = ctx->pkt;
8b453a2b
TS
485 target_ulong next_PC = ctx->base.pc_next + pkt->encod_pkt_size_in_bytes;
486 int i;
487
488 /* Clear out the disassembly context */
613653e5 489 ctx->next_PC = next_PC;
8b453a2b
TS
490 ctx->reg_log_idx = 0;
491 bitmap_zero(ctx->regs_written, TOTAL_PER_THREAD_REGS);
b9f0326b 492 bitmap_zero(ctx->regs_read, TOTAL_PER_THREAD_REGS);
10849c26 493 bitmap_zero(ctx->predicated_regs, TOTAL_PER_THREAD_REGS);
8b453a2b 494 ctx->preg_log_idx = 0;
6c677c60 495 bitmap_zero(ctx->pregs_written, NUM_PREGS);
b9f0326b 496 bitmap_zero(ctx->pregs_read, NUM_PREGS);
a82dd548
TS
497 ctx->future_vregs_idx = 0;
498 ctx->tmp_vregs_idx = 0;
499 ctx->vreg_log_idx = 0;
500 bitmap_zero(ctx->vregs_updated_tmp, NUM_VREGS);
501 bitmap_zero(ctx->vregs_updated, NUM_VREGS);
502 bitmap_zero(ctx->vregs_select, NUM_VREGS);
4d6f8420
TS
503 bitmap_zero(ctx->predicated_future_vregs, NUM_VREGS);
504 bitmap_zero(ctx->predicated_tmp_vregs, NUM_VREGS);
b9f0326b
TS
505 bitmap_zero(ctx->vregs_read, NUM_VREGS);
506 bitmap_zero(ctx->qregs_read, NUM_QREGS);
a82dd548 507 ctx->qreg_log_idx = 0;
8b453a2b
TS
508 for (i = 0; i < STORES_MAX; i++) {
509 ctx->store_width[i] = 0;
510 }
92cfa25f 511 ctx->s1_store_processed = false;
a82dd548 512 ctx->pre_commit = true;
4ff56764
TS
513 for (i = 0; i < TOTAL_PER_THREAD_REGS; i++) {
514 ctx->new_value[i] = NULL;
515 }
e22edc7c
TS
516 for (i = 0; i < NUM_PREGS; i++) {
517 ctx->new_pred_value[i] = NULL;
518 }
8b453a2b 519
10849c26
TS
520 analyze_packet(ctx);
521
522 /*
523 * pregs_written is used both in the analyze phase as well as the code
524 * gen phase, so clear it again.
525 */
526 bitmap_zero(ctx->pregs_written, NUM_PREGS);
527
85580a65
TS
528 if (HEX_DEBUG) {
529 /* Handy place to set a breakpoint before the packet executes */
530 gen_helper_debug_start_packet(cpu_env);
85580a65 531 }
8b453a2b
TS
532
533 /* Initialize the runtime state for packet semantics */
8b453a2b
TS
534 if (need_slot_cancelled(pkt)) {
535 tcg_gen_movi_tl(hex_slot_cancelled, 0);
536 }
0fc56c43 537 ctx->branch_taken = NULL;
8b453a2b 538 if (pkt->pkt_has_cof) {
0fc56c43 539 ctx->branch_taken = tcg_temp_new();
fb67c2bf 540 if (pkt->pkt_has_multi_cof) {
0fc56c43 541 tcg_gen_movi_tl(ctx->branch_taken, 0);
fb67c2bf 542 }
613653e5
TS
543 if (need_next_PC(ctx)) {
544 tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], next_PC);
545 }
8b453a2b 546 }
25e1d87d 547 if (HEX_DEBUG) {
842b206f
TS
548 ctx->pred_written = tcg_temp_new();
549 tcg_gen_movi_tl(ctx->pred_written, 0);
8b453a2b 550 }
a82dd548 551
6aa4f1d1 552 /* Preload the predicated registers into get_result_gpr(ctx, i) */
d54c5615
TS
553 if (ctx->need_commit &&
554 !bitmap_empty(ctx->predicated_regs, TOTAL_PER_THREAD_REGS)) {
10849c26
TS
555 int i = find_first_bit(ctx->predicated_regs, TOTAL_PER_THREAD_REGS);
556 while (i < TOTAL_PER_THREAD_REGS) {
6aa4f1d1 557 tcg_gen_mov_tl(get_result_gpr(ctx, i), hex_gpr[i]);
10849c26
TS
558 i = find_next_bit(ctx->predicated_regs, TOTAL_PER_THREAD_REGS,
559 i + 1);
560 }
561 }
562
25e1d87d 563 /*
2babbd93 564 * Preload the predicated pred registers into ctx->new_pred_value[pred_num]
25e1d87d
TS
565 * Only endloop instructions conditionally write to pred registers
566 */
455e169d 567 if (ctx->need_commit && pkt->pkt_has_endloop) {
25e1d87d
TS
568 for (int i = 0; i < ctx->preg_log_idx; i++) {
569 int pred_num = ctx->preg_log[i];
e22edc7c
TS
570 ctx->new_pred_value[pred_num] = tcg_temp_new();
571 tcg_gen_mov_tl(ctx->new_pred_value[pred_num], hex_pred[pred_num]);
25e1d87d
TS
572 }
573 }
574
4d6f8420
TS
575 /* Preload the predicated HVX registers into future_VRegs and tmp_VRegs */
576 if (!bitmap_empty(ctx->predicated_future_vregs, NUM_VREGS)) {
577 int i = find_first_bit(ctx->predicated_future_vregs, NUM_VREGS);
578 while (i < NUM_VREGS) {
579 const intptr_t VdV_off =
580 ctx_future_vreg_off(ctx, i, 1, true);
581 intptr_t src_off = offsetof(CPUHexagonState, VRegs[i]);
582 tcg_gen_gvec_mov(MO_64, VdV_off,
583 src_off,
584 sizeof(MMVector),
585 sizeof(MMVector));
586 i = find_next_bit(ctx->predicated_future_vregs, NUM_VREGS, i + 1);
587 }
588 }
589 if (!bitmap_empty(ctx->predicated_tmp_vregs, NUM_VREGS)) {
590 int i = find_first_bit(ctx->predicated_tmp_vregs, NUM_VREGS);
591 while (i < NUM_VREGS) {
592 const intptr_t VdV_off =
593 ctx_tmp_vreg_off(ctx, i, 1, true);
594 intptr_t src_off = offsetof(CPUHexagonState, VRegs[i]);
595 tcg_gen_gvec_mov(MO_64, VdV_off,
596 src_off,
597 sizeof(MMVector),
598 sizeof(MMVector));
599 i = find_next_bit(ctx->predicated_tmp_vregs, NUM_VREGS, i + 1);
600 }
601 }
a82dd548
TS
602}
603
1e536334 604bool is_gather_store_insn(DisasContext *ctx)
a82dd548 605{
1e536334
TS
606 Packet *pkt = ctx->pkt;
607 Insn *insn = ctx->insn;
a82dd548
TS
608 if (GET_ATTRIB(insn->opcode, A_CVI_NEW) &&
609 insn->new_value_producer_slot == 1) {
610 /* Look for gather instruction */
611 for (int i = 0; i < pkt->num_insns; i++) {
612 Insn *in = &pkt->insn[i];
613 if (GET_ATTRIB(in->opcode, A_CVI_GATHER) && in->slot == 1) {
614 return true;
615 }
616 }
617 }
618 return false;
8b453a2b
TS
619}
620
1e536334 621static void mark_store_width(DisasContext *ctx)
661ad999 622{
1e536334
TS
623 uint16_t opcode = ctx->insn->opcode;
624 uint32_t slot = ctx->insn->slot;
661ad999
TS
625 uint8_t width = 0;
626
627 if (GET_ATTRIB(opcode, A_SCALAR_STORE)) {
406c74f2
TS
628 if (GET_ATTRIB(opcode, A_MEMSIZE_0B)) {
629 return;
630 }
661ad999
TS
631 if (GET_ATTRIB(opcode, A_MEMSIZE_1B)) {
632 width |= 1;
633 }
634 if (GET_ATTRIB(opcode, A_MEMSIZE_2B)) {
635 width |= 2;
636 }
637 if (GET_ATTRIB(opcode, A_MEMSIZE_4B)) {
638 width |= 4;
639 }
640 if (GET_ATTRIB(opcode, A_MEMSIZE_8B)) {
641 width |= 8;
642 }
643 tcg_debug_assert(is_power_of_2(width));
644 ctx->store_width[slot] = width;
645 }
646}
647
1e536334 648static void gen_insn(DisasContext *ctx)
8b453a2b 649{
1e536334 650 if (ctx->insn->generate) {
1e536334 651 ctx->insn->generate(ctx);
1e536334 652 mark_store_width(ctx);
8b453a2b 653 } else {
743debbc 654 gen_exception_end_tb(ctx, HEX_EXCP_INVALID_OPCODE);
8b453a2b
TS
655 }
656}
657
658/*
659 * Helpers for generating the packet commit
660 */
661static void gen_reg_writes(DisasContext *ctx)
662{
663 int i;
664
d54c5615
TS
665 /* Early exit if not needed */
666 if (!ctx->need_commit) {
667 return;
668 }
669
8b453a2b
TS
670 for (i = 0; i < ctx->reg_log_idx; i++) {
671 int reg_num = ctx->reg_log[i];
672
6aa4f1d1 673 tcg_gen_mov_tl(hex_gpr[reg_num], get_result_gpr(ctx, reg_num));
564b2040
TS
674
675 /*
676 * ctx->is_tight_loop is set when SA0 points to the beginning of the TB.
677 * If we write to SA0, we have to turn off tight loop handling.
678 */
679 if (reg_num == HEX_REG_SA0) {
680 ctx->is_tight_loop = false;
681 }
8b453a2b
TS
682 }
683}
684
1e536334 685static void gen_pred_writes(DisasContext *ctx)
8b453a2b 686{
455e169d
TS
687 /* Early exit if not needed or the log is empty */
688 if (!ctx->need_commit || !ctx->preg_log_idx) {
8b453a2b
TS
689 return;
690 }
691
25e1d87d
TS
692 for (int i = 0; i < ctx->preg_log_idx; i++) {
693 int pred_num = ctx->preg_log[i];
e22edc7c 694 tcg_gen_mov_tl(hex_pred[pred_num], ctx->new_pred_value[pred_num]);
8b453a2b 695 }
8b453a2b
TS
696}
697
a27c100c 698static void gen_check_store_width(DisasContext *ctx, int slot_num)
8b453a2b 699{
85580a65 700 if (HEX_DEBUG) {
23803bbe
PMD
701 TCGv slot = tcg_constant_tl(slot_num);
702 TCGv check = tcg_constant_tl(ctx->store_width[slot_num]);
85580a65 703 gen_helper_debug_check_store_width(cpu_env, slot, check);
85580a65 704 }
a27c100c 705}
8b453a2b
TS
706
707static bool slot_is_predicated(Packet *pkt, int slot_num)
708{
709 for (int i = 0; i < pkt->num_insns; i++) {
710 if (pkt->insn[i].slot == slot_num) {
711 return GET_ATTRIB(pkt->insn[i].opcode, A_CONDEXEC);
712 }
713 }
714 /* If we get to here, we didn't find an instruction in the requested slot */
715 g_assert_not_reached();
716}
717
1e536334 718void process_store(DisasContext *ctx, int slot_num)
8b453a2b 719{
1e536334 720 bool is_predicated = slot_is_predicated(ctx->pkt, slot_num);
8b453a2b
TS
721 TCGLabel *label_end = NULL;
722
723 /*
724 * We may have already processed this store
725 * See CHECK_NOSHUF in macros.h
726 */
727 if (slot_num == 1 && ctx->s1_store_processed) {
728 return;
729 }
92cfa25f 730 ctx->s1_store_processed = true;
8b453a2b
TS
731
732 if (is_predicated) {
733 TCGv cancelled = tcg_temp_new();
734 label_end = gen_new_label();
735
736 /* Don't do anything if the slot was cancelled */
737 tcg_gen_extract_tl(cancelled, hex_slot_cancelled, slot_num, 1);
738 tcg_gen_brcondi_tl(TCG_COND_NE, cancelled, 0, label_end);
8b453a2b
TS
739 }
740 {
7a819de8 741 TCGv address = tcg_temp_new();
8b453a2b
TS
742 tcg_gen_mov_tl(address, hex_store_addr[slot_num]);
743
744 /*
745 * If we know the width from the DisasContext, we can
746 * generate much cleaner code.
747 * Unfortunately, not all instructions execute the fSTORE
748 * macro during code generation. Anything that uses the
749 * generic helper will have this problem. Instructions
750 * that use fWRAP to generate proper TCG code will be OK.
751 */
752 switch (ctx->store_width[slot_num]) {
753 case 1:
a27c100c 754 gen_check_store_width(ctx, slot_num);
53b26d25
RH
755 tcg_gen_qemu_st_tl(hex_store_val32[slot_num],
756 hex_store_addr[slot_num],
757 ctx->mem_idx, MO_UB);
8b453a2b
TS
758 break;
759 case 2:
a27c100c 760 gen_check_store_width(ctx, slot_num);
53b26d25
RH
761 tcg_gen_qemu_st_tl(hex_store_val32[slot_num],
762 hex_store_addr[slot_num],
763 ctx->mem_idx, MO_TEUW);
8b453a2b
TS
764 break;
765 case 4:
a27c100c 766 gen_check_store_width(ctx, slot_num);
53b26d25
RH
767 tcg_gen_qemu_st_tl(hex_store_val32[slot_num],
768 hex_store_addr[slot_num],
769 ctx->mem_idx, MO_TEUL);
8b453a2b
TS
770 break;
771 case 8:
a27c100c 772 gen_check_store_width(ctx, slot_num);
53b26d25
RH
773 tcg_gen_qemu_st_i64(hex_store_val64[slot_num],
774 hex_store_addr[slot_num],
775 ctx->mem_idx, MO_TEUQ);
8b453a2b
TS
776 break;
777 default:
778 {
779 /*
780 * If we get to here, we don't know the width at
781 * TCG generation time, we'll use a helper to
782 * avoid branching based on the width at runtime.
783 */
23803bbe 784 TCGv slot = tcg_constant_tl(slot_num);
8b453a2b 785 gen_helper_commit_store(cpu_env, slot);
8b453a2b
TS
786 }
787 }
8b453a2b
TS
788 }
789 if (is_predicated) {
790 gen_set_label(label_end);
791 }
792}
793
1e536334 794static void process_store_log(DisasContext *ctx)
8b453a2b
TS
795{
796 /*
797 * When a packet has two stores, the hardware processes
c23b5764 798 * slot 1 and then slot 0. This will be important when
8b453a2b
TS
799 * the memory accesses overlap.
800 */
1e536334 801 Packet *pkt = ctx->pkt;
e2be9a5c
TS
802 if (pkt->pkt_has_store_s1) {
803 g_assert(!pkt->pkt_has_dczeroa);
1e536334 804 process_store(ctx, 1);
8b453a2b 805 }
e2be9a5c
TS
806 if (pkt->pkt_has_store_s0) {
807 g_assert(!pkt->pkt_has_dczeroa);
1e536334 808 process_store(ctx, 0);
8b453a2b
TS
809 }
810}
811
812/* Zero out a 32-bit cache line */
1e536334 813static void process_dczeroa(DisasContext *ctx)
8b453a2b 814{
1e536334 815 if (ctx->pkt->pkt_has_dczeroa) {
8b453a2b
TS
816 /* Store 32 bytes of zero starting at (addr & ~0x1f) */
817 TCGv addr = tcg_temp_new();
23803bbe 818 TCGv_i64 zero = tcg_constant_i64(0);
8b453a2b 819
0fc56c43 820 tcg_gen_andi_tl(addr, ctx->dczero_addr, ~0x1f);
53b26d25 821 tcg_gen_qemu_st_i64(zero, addr, ctx->mem_idx, MO_UQ);
8b453a2b 822 tcg_gen_addi_tl(addr, addr, 8);
53b26d25 823 tcg_gen_qemu_st_i64(zero, addr, ctx->mem_idx, MO_UQ);
8b453a2b 824 tcg_gen_addi_tl(addr, addr, 8);
53b26d25 825 tcg_gen_qemu_st_i64(zero, addr, ctx->mem_idx, MO_UQ);
8b453a2b 826 tcg_gen_addi_tl(addr, addr, 8);
53b26d25 827 tcg_gen_qemu_st_i64(zero, addr, ctx->mem_idx, MO_UQ);
8b453a2b
TS
828 }
829}
830
a82dd548
TS
831static bool pkt_has_hvx_store(Packet *pkt)
832{
833 int i;
834 for (i = 0; i < pkt->num_insns; i++) {
835 int opcode = pkt->insn[i].opcode;
836 if (GET_ATTRIB(opcode, A_CVI) && GET_ATTRIB(opcode, A_STORE)) {
837 return true;
838 }
839 }
840 return false;
841}
842
1e536334 843static void gen_commit_hvx(DisasContext *ctx)
a82dd548
TS
844{
845 int i;
846
b8552985
TS
847 /* Early exit if not needed */
848 if (!ctx->need_commit) {
849 g_assert(!pkt_has_hvx_store(ctx->pkt));
850 return;
851 }
852
a82dd548
TS
853 /*
854 * for (i = 0; i < ctx->vreg_log_idx; i++) {
855 * int rnum = ctx->vreg_log[i];
c2b33d0b 856 * env->VRegs[rnum] = env->future_VRegs[rnum];
a82dd548
TS
857 * }
858 */
859 for (i = 0; i < ctx->vreg_log_idx; i++) {
860 int rnum = ctx->vreg_log[i];
a82dd548
TS
861 intptr_t dstoff = offsetof(CPUHexagonState, VRegs[rnum]);
862 intptr_t srcoff = ctx_future_vreg_off(ctx, rnum, 1, false);
863 size_t size = sizeof(MMVector);
864
c2b33d0b 865 tcg_gen_gvec_mov(MO_64, dstoff, srcoff, size, size);
a82dd548
TS
866 }
867
868 /*
869 * for (i = 0; i < ctx->qreg_log_idx; i++) {
870 * int rnum = ctx->qreg_log[i];
c2b33d0b 871 * env->QRegs[rnum] = env->future_QRegs[rnum];
a82dd548
TS
872 * }
873 */
874 for (i = 0; i < ctx->qreg_log_idx; i++) {
875 int rnum = ctx->qreg_log[i];
a82dd548
TS
876 intptr_t dstoff = offsetof(CPUHexagonState, QRegs[rnum]);
877 intptr_t srcoff = offsetof(CPUHexagonState, future_QRegs[rnum]);
878 size_t size = sizeof(MMQReg);
879
c2b33d0b 880 tcg_gen_gvec_mov(MO_64, dstoff, srcoff, size, size);
a82dd548
TS
881 }
882
1e536334 883 if (pkt_has_hvx_store(ctx->pkt)) {
a82dd548
TS
884 gen_helper_commit_hvx_stores(cpu_env);
885 }
886}
887
1e536334 888static void update_exec_counters(DisasContext *ctx)
8b453a2b 889{
1e536334 890 Packet *pkt = ctx->pkt;
8b453a2b
TS
891 int num_insns = pkt->num_insns;
892 int num_real_insns = 0;
a82dd548 893 int num_hvx_insns = 0;
8b453a2b
TS
894
895 for (int i = 0; i < num_insns; i++) {
896 if (!pkt->insn[i].is_endloop &&
897 !pkt->insn[i].part1 &&
898 !GET_ATTRIB(pkt->insn[i].opcode, A_IT_NOP)) {
899 num_real_insns++;
900 }
a82dd548
TS
901 if (GET_ATTRIB(pkt->insn[i].opcode, A_CVI)) {
902 num_hvx_insns++;
903 }
8b453a2b
TS
904 }
905
906 ctx->num_packets++;
907 ctx->num_insns += num_real_insns;
a82dd548 908 ctx->num_hvx_insns += num_hvx_insns;
8b453a2b
TS
909}
910
1e536334 911static void gen_commit_packet(DisasContext *ctx)
8b453a2b 912{
c23b5764
TS
913 /*
914 * If there is more than one store in a packet, make sure they are all OK
915 * before proceeding with the rest of the packet commit.
916 *
917 * dczeroa has to be the only store operation in the packet, so we go
918 * ahead and process that first.
919 *
a82dd548
TS
920 * When there is an HVX store, there can also be a scalar store in either
921 * slot 0 or slot1, so we create a mask for the helper to indicate what
922 * work to do.
923 *
c23b5764
TS
924 * When there are two scalar stores, we probe the one in slot 0.
925 *
926 * Note that we don't call the probe helper for packets with only one
927 * store. Therefore, we call process_store_log before anything else
928 * involved in committing the packet.
929 */
1e536334 930 Packet *pkt = ctx->pkt;
c23b5764
TS
931 bool has_store_s0 = pkt->pkt_has_store_s0;
932 bool has_store_s1 = (pkt->pkt_has_store_s1 && !ctx->s1_store_processed);
a82dd548 933 bool has_hvx_store = pkt_has_hvx_store(pkt);
c23b5764
TS
934 if (pkt->pkt_has_dczeroa) {
935 /*
936 * The dczeroa will be the store in slot 0, check that we don't have
a82dd548 937 * a store in slot 1 or an HVX store.
c23b5764 938 */
e2be9a5c 939 g_assert(!has_store_s1 && !has_hvx_store);
1e536334 940 process_dczeroa(ctx);
a82dd548 941 } else if (has_hvx_store) {
a82dd548 942 if (!has_store_s0 && !has_store_s1) {
2bda44e8 943 TCGv mem_idx = tcg_constant_tl(ctx->mem_idx);
a82dd548
TS
944 gen_helper_probe_hvx_stores(cpu_env, mem_idx);
945 } else {
946 int mask = 0;
a82dd548
TS
947
948 if (has_store_s0) {
7b84fd04
TS
949 mask =
950 FIELD_DP32(mask, PROBE_PKT_SCALAR_HVX_STORES, HAS_ST0, 1);
a82dd548
TS
951 }
952 if (has_store_s1) {
7b84fd04
TS
953 mask =
954 FIELD_DP32(mask, PROBE_PKT_SCALAR_HVX_STORES, HAS_ST1, 1);
a82dd548
TS
955 }
956 if (has_hvx_store) {
7b84fd04
TS
957 mask =
958 FIELD_DP32(mask, PROBE_PKT_SCALAR_HVX_STORES,
959 HAS_HVX_STORES, 1);
960 }
961 if (has_store_s0 && slot_is_predicated(pkt, 0)) {
962 mask =
963 FIELD_DP32(mask, PROBE_PKT_SCALAR_HVX_STORES,
964 S0_IS_PRED, 1);
965 }
966 if (has_store_s1 && slot_is_predicated(pkt, 1)) {
967 mask =
968 FIELD_DP32(mask, PROBE_PKT_SCALAR_HVX_STORES,
969 S1_IS_PRED, 1);
a82dd548 970 }
2bda44e8
TS
971 mask = FIELD_DP32(mask, PROBE_PKT_SCALAR_HVX_STORES, MMU_IDX,
972 ctx->mem_idx);
973 gen_helper_probe_pkt_scalar_hvx_stores(cpu_env,
974 tcg_constant_tl(mask));
a82dd548 975 }
c23b5764
TS
976 } else if (has_store_s0 && has_store_s1) {
977 /*
978 * process_store_log will execute the slot 1 store first,
979 * so we only have to probe the store in slot 0
980 */
7b84fd04
TS
981 int args = 0;
982 args =
983 FIELD_DP32(args, PROBE_PKT_SCALAR_STORE_S0, MMU_IDX, ctx->mem_idx);
984 if (slot_is_predicated(pkt, 0)) {
985 args =
986 FIELD_DP32(args, PROBE_PKT_SCALAR_STORE_S0, IS_PREDICATED, 1);
987 }
988 TCGv args_tcgv = tcg_constant_tl(args);
989 gen_helper_probe_pkt_scalar_store_s0(cpu_env, args_tcgv);
c23b5764
TS
990 }
991
1e536334 992 process_store_log(ctx);
c23b5764 993
8b453a2b 994 gen_reg_writes(ctx);
1e536334 995 gen_pred_writes(ctx);
a82dd548 996 if (pkt->pkt_has_hvx) {
1e536334 997 gen_commit_hvx(ctx);
a82dd548 998 }
1e536334 999 update_exec_counters(ctx);
85580a65 1000 if (HEX_DEBUG) {
8b453a2b 1001 TCGv has_st0 =
23803bbe 1002 tcg_constant_tl(pkt->pkt_has_store_s0 && !pkt->pkt_has_dczeroa);
8b453a2b 1003 TCGv has_st1 =
23803bbe 1004 tcg_constant_tl(pkt->pkt_has_store_s1 && !pkt->pkt_has_dczeroa);
8b453a2b
TS
1005
1006 /* Handy place to set a breakpoint at the end of execution */
0fc56c43
TS
1007 gen_helper_debug_commit_end(cpu_env, tcg_constant_tl(ctx->pkt->pc),
1008 ctx->pred_written, has_st0, has_st1);
8b453a2b 1009 }
8b453a2b 1010
a82dd548
TS
1011 if (pkt->vhist_insn != NULL) {
1012 ctx->pre_commit = false;
1e536334
TS
1013 ctx->insn = pkt->vhist_insn;
1014 pkt->vhist_insn->generate(ctx);
a82dd548
TS
1015 }
1016
8b453a2b 1017 if (pkt->pkt_has_cof) {
743debbc 1018 gen_end_tb(ctx);
8b453a2b
TS
1019 }
1020}
1021
1022static void decode_and_translate_packet(CPUHexagonState *env, DisasContext *ctx)
1023{
1024 uint32_t words[PACKET_WORDS_MAX];
1025 int nwords;
1026 Packet pkt;
1027 int i;
1028
1029 nwords = read_packet_words(env, ctx, words);
1030 if (!nwords) {
743debbc 1031 gen_exception_end_tb(ctx, HEX_EXCP_INVALID_PACKET);
8b453a2b
TS
1032 return;
1033 }
1034
1035 if (decode_packet(nwords, words, &pkt, false) > 0) {
40085901 1036 pkt.pc = ctx->base.pc_next;
8b453a2b 1037 HEX_DEBUG_PRINT_PKT(&pkt);
1e536334
TS
1038 ctx->pkt = &pkt;
1039 gen_start_packet(ctx);
8b453a2b 1040 for (i = 0; i < pkt.num_insns; i++) {
1e536334
TS
1041 ctx->insn = &pkt.insn[i];
1042 gen_insn(ctx);
8b453a2b 1043 }
1e536334 1044 gen_commit_packet(ctx);
8b453a2b
TS
1045 ctx->base.pc_next += pkt.encod_pkt_size_in_bytes;
1046 } else {
743debbc 1047 gen_exception_end_tb(ctx, HEX_EXCP_INVALID_PACKET);
8b453a2b
TS
1048 }
1049}
1050
1051static void hexagon_tr_init_disas_context(DisasContextBase *dcbase,
1052 CPUState *cs)
1053{
1054 DisasContext *ctx = container_of(dcbase, DisasContext, base);
d54c5615 1055 HexagonCPU *hex_cpu = env_archcpu(cs->env_ptr);
564b2040 1056 uint32_t hex_flags = dcbase->tb->flags;
8b453a2b
TS
1057
1058 ctx->mem_idx = MMU_USER_IDX;
1059 ctx->num_packets = 0;
1060 ctx->num_insns = 0;
a82dd548 1061 ctx->num_hvx_insns = 0;
1b9a7f2a 1062 ctx->branch_cond = TCG_COND_NEVER;
564b2040 1063 ctx->is_tight_loop = FIELD_EX32(hex_flags, TB_FLAGS, IS_TIGHT_LOOP);
d54c5615 1064 ctx->short_circuit = hex_cpu->short_circuit;
8b453a2b
TS
1065}
1066
1067static void hexagon_tr_tb_start(DisasContextBase *db, CPUState *cpu)
1068{
1069}
1070
1071static void hexagon_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
1072{
1073 DisasContext *ctx = container_of(dcbase, DisasContext, base);
1074
1075 tcg_gen_insn_start(ctx->base.pc_next);
1076}
1077
8b453a2b
TS
1078static bool pkt_crosses_page(CPUHexagonState *env, DisasContext *ctx)
1079{
1080 target_ulong page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
1081 bool found_end = false;
1082 int nwords;
1083
1084 for (nwords = 0; !found_end && nwords < PACKET_WORDS_MAX; nwords++) {
1085 uint32_t word = cpu_ldl_code(env,
1086 ctx->base.pc_next + nwords * sizeof(uint32_t));
1087 found_end = is_packet_end(word);
1088 }
1089 uint32_t next_ptr = ctx->base.pc_next + nwords * sizeof(uint32_t);
1090 return found_end && next_ptr - page_start >= TARGET_PAGE_SIZE;
1091}
1092
1093static void hexagon_tr_translate_packet(DisasContextBase *dcbase, CPUState *cpu)
1094{
1095 DisasContext *ctx = container_of(dcbase, DisasContext, base);
1096 CPUHexagonState *env = cpu->env_ptr;
1097
1098 decode_and_translate_packet(env, ctx);
1099
1100 if (ctx->base.is_jmp == DISAS_NEXT) {
1101 target_ulong page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
1102 target_ulong bytes_max = PACKET_WORDS_MAX * sizeof(target_ulong);
1103
1104 if (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE ||
1105 (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE - bytes_max &&
1106 pkt_crosses_page(env, ctx))) {
1107 ctx->base.is_jmp = DISAS_TOO_MANY;
1108 }
1109
1110 /*
1111 * The CPU log is used to compare against LLDB single stepping,
1112 * so end the TLB after every packet.
1113 */
7d9ab202 1114 HexagonCPU *hex_cpu = env_archcpu(env);
8b453a2b
TS
1115 if (hex_cpu->lldb_compat && qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
1116 ctx->base.is_jmp = DISAS_TOO_MANY;
1117 }
8b453a2b
TS
1118 }
1119}
1120
1121static void hexagon_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
1122{
1123 DisasContext *ctx = container_of(dcbase, DisasContext, base);
1124
1125 switch (ctx->base.is_jmp) {
1126 case DISAS_TOO_MANY:
1127 gen_exec_counters(ctx);
1128 tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], ctx->base.pc_next);
db07bd02 1129 tcg_gen_exit_tb(NULL, 0);
8b453a2b
TS
1130 break;
1131 case DISAS_NORETURN:
8b453a2b
TS
1132 break;
1133 default:
1134 g_assert_not_reached();
1135 }
1136}
1137
8eb806a7
RH
1138static void hexagon_tr_disas_log(const DisasContextBase *dcbase,
1139 CPUState *cpu, FILE *logfile)
8b453a2b 1140{
8eb806a7
RH
1141 fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first));
1142 target_disas(logfile, cpu, dcbase->pc_first, dcbase->tb->size);
8b453a2b
TS
1143}
1144
1145
1146static const TranslatorOps hexagon_tr_ops = {
1147 .init_disas_context = hexagon_tr_init_disas_context,
1148 .tb_start = hexagon_tr_tb_start,
1149 .insn_start = hexagon_tr_insn_start,
8b453a2b
TS
1150 .translate_insn = hexagon_tr_translate_packet,
1151 .tb_stop = hexagon_tr_tb_stop,
1152 .disas_log = hexagon_tr_disas_log,
1153};
1154
597f9b2d 1155void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
306c8721 1156 target_ulong pc, void *host_pc)
8b453a2b
TS
1157{
1158 DisasContext ctx;
1159
306c8721
RH
1160 translator_loop(cs, tb, max_insns, pc, host_pc,
1161 &hexagon_tr_ops, &ctx.base);
8b453a2b
TS
1162}
1163
1164#define NAME_LEN 64
8b453a2b 1165static char reg_written_names[TOTAL_PER_THREAD_REGS][NAME_LEN];
8b453a2b
TS
1166static char store_addr_names[STORES_MAX][NAME_LEN];
1167static char store_width_names[STORES_MAX][NAME_LEN];
1168static char store_val32_names[STORES_MAX][NAME_LEN];
1169static char store_val64_names[STORES_MAX][NAME_LEN];
a82dd548
TS
1170static char vstore_addr_names[VSTORES_MAX][NAME_LEN];
1171static char vstore_size_names[VSTORES_MAX][NAME_LEN];
1172static char vstore_pending_names[VSTORES_MAX][NAME_LEN];
8b453a2b
TS
1173
1174void hexagon_translate_init(void)
1175{
1176 int i;
1177
1178 opcode_init();
1179
8b453a2b
TS
1180 for (i = 0; i < TOTAL_PER_THREAD_REGS; i++) {
1181 hex_gpr[i] = tcg_global_mem_new(cpu_env,
1182 offsetof(CPUHexagonState, gpr[i]),
1183 hexagon_regnames[i]);
1184
85580a65
TS
1185 if (HEX_DEBUG) {
1186 snprintf(reg_written_names[i], NAME_LEN, "reg_written_%s",
1187 hexagon_regnames[i]);
1188 hex_reg_written[i] = tcg_global_mem_new(cpu_env,
1189 offsetof(CPUHexagonState, reg_written[i]),
1190 reg_written_names[i]);
1191 }
8b453a2b 1192 }
6aa4f1d1
TS
1193 hex_new_value_usr = tcg_global_mem_new(cpu_env,
1194 offsetof(CPUHexagonState, new_value_usr), "new_value_usr");
1195
8b453a2b
TS
1196 for (i = 0; i < NUM_PREGS; i++) {
1197 hex_pred[i] = tcg_global_mem_new(cpu_env,
1198 offsetof(CPUHexagonState, pred[i]),
1199 hexagon_prednames[i]);
8b453a2b 1200 }
8b453a2b
TS
1201 hex_slot_cancelled = tcg_global_mem_new(cpu_env,
1202 offsetof(CPUHexagonState, slot_cancelled), "slot_cancelled");
8b453a2b
TS
1203 hex_llsc_addr = tcg_global_mem_new(cpu_env,
1204 offsetof(CPUHexagonState, llsc_addr), "llsc_addr");
1205 hex_llsc_val = tcg_global_mem_new(cpu_env,
1206 offsetof(CPUHexagonState, llsc_val), "llsc_val");
1207 hex_llsc_val_i64 = tcg_global_mem_new_i64(cpu_env,
1208 offsetof(CPUHexagonState, llsc_val_i64), "llsc_val_i64");
1209 for (i = 0; i < STORES_MAX; i++) {
1210 snprintf(store_addr_names[i], NAME_LEN, "store_addr_%d", i);
1211 hex_store_addr[i] = tcg_global_mem_new(cpu_env,
1212 offsetof(CPUHexagonState, mem_log_stores[i].va),
1213 store_addr_names[i]);
1214
1215 snprintf(store_width_names[i], NAME_LEN, "store_width_%d", i);
1216 hex_store_width[i] = tcg_global_mem_new(cpu_env,
1217 offsetof(CPUHexagonState, mem_log_stores[i].width),
1218 store_width_names[i]);
1219
1220 snprintf(store_val32_names[i], NAME_LEN, "store_val32_%d", i);
1221 hex_store_val32[i] = tcg_global_mem_new(cpu_env,
1222 offsetof(CPUHexagonState, mem_log_stores[i].data32),
1223 store_val32_names[i]);
1224
1225 snprintf(store_val64_names[i], NAME_LEN, "store_val64_%d", i);
1226 hex_store_val64[i] = tcg_global_mem_new_i64(cpu_env,
1227 offsetof(CPUHexagonState, mem_log_stores[i].data64),
1228 store_val64_names[i]);
1229 }
a82dd548
TS
1230 for (int i = 0; i < VSTORES_MAX; i++) {
1231 snprintf(vstore_addr_names[i], NAME_LEN, "vstore_addr_%d", i);
1232 hex_vstore_addr[i] = tcg_global_mem_new(cpu_env,
1233 offsetof(CPUHexagonState, vstore[i].va),
1234 vstore_addr_names[i]);
1235
1236 snprintf(vstore_size_names[i], NAME_LEN, "vstore_size_%d", i);
1237 hex_vstore_size[i] = tcg_global_mem_new(cpu_env,
1238 offsetof(CPUHexagonState, vstore[i].size),
1239 vstore_size_names[i]);
1240
1241 snprintf(vstore_pending_names[i], NAME_LEN, "vstore_pending_%d", i);
1242 hex_vstore_pending[i] = tcg_global_mem_new(cpu_env,
1243 offsetof(CPUHexagonState, vstore_pending[i]),
1244 vstore_pending_names[i]);
1245 }
8b453a2b 1246}