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