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