master
c 1,407 lines 44.1 KB
Raw
1 /*
2 * Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. All Rights Reserved.
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"
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 "accel/tcg/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 #include "exec/target_page.h"
36
37 #define HELPER_H "helper.h"
38 #include "exec/helper-info.c.inc"
39 #undef HELPER_H
40
41 /* Forward declarations referenced in analyze_funcs_generated.c.inc */
42 static void mark_implicit_reads(DisasContext *ctx);
43 static void mark_implicit_writes(DisasContext *ctx);
44
45 #include "analyze_funcs_generated.c.inc"
46
47 typedef void (*AnalyzeInsn)(DisasContext *ctx);
48 static const AnalyzeInsn opcode_analyze[XX_LAST_OPCODE] = {
49 #define OPCODE(X) [X] = analyze_##X
50 #include "opcodes_def_generated.h.inc"
51 #undef OPCODE
52 };
53
54 TCGv hex_gpr[TOTAL_PER_THREAD_REGS];
55 TCGv hex_pred[NUM_PREGS];
56 TCGv hex_slot_cancelled;
57 TCGv hex_next_PC;
58 TCGv hex_new_value_usr;
59 TCGv hex_store_addr[STORES_MAX];
60 TCGv_i32 hex_store_width[STORES_MAX];
61 TCGv hex_store_val32[STORES_MAX];
62 TCGv_i64 hex_store_val64[STORES_MAX];
63 TCGv hex_llsc_addr;
64 TCGv hex_llsc_val;
65 TCGv_i64 hex_llsc_val_i64;
66 #ifndef CONFIG_USER_ONLY
67 TCGv_i64 hex_cycle_count;
68 #endif
69 TCGv hex_vstore_addr[VSTORES_MAX];
70 TCGv hex_vstore_size[VSTORES_MAX];
71 TCGv hex_vstore_pending[VSTORES_MAX];
72
73 #ifndef CONFIG_USER_ONLY
74 TCGv_i32 hex_greg[NUM_GREGS];
75 TCGv_i32 hex_t_sreg[NUM_SREGS];
76 TCGv_i32 hex_cause_code;
77 #endif
78
79 static const char * const hexagon_prednames[] = {
80 "p0", "p1", "p2", "p3"
81 };
82
83 intptr_t ctx_future_vreg_off(DisasContext *ctx, int regnum,
84 int num, bool alloc_ok)
85 {
86 intptr_t offset;
87
88 if (!ctx->need_commit) {
89 return offsetof(CPUHexagonState, VRegs[regnum]);
90 }
91
92 /* See if it is already allocated */
93 for (int i = 0; i < ctx->future_vregs_idx; i++) {
94 if (ctx->future_vregs_num[i] == regnum) {
95 return offsetof(CPUHexagonState, future_VRegs[i]);
96 }
97 }
98
99 g_assert(alloc_ok);
100 offset = offsetof(CPUHexagonState, future_VRegs[ctx->future_vregs_idx]);
101 for (int i = 0; i < num; i++) {
102 ctx->future_vregs_num[ctx->future_vregs_idx + i] = regnum++;
103 }
104 ctx->future_vregs_idx += num;
105 g_assert(ctx->future_vregs_idx <= VECTOR_TEMPS_MAX);
106 return offset;
107 }
108
109 intptr_t ctx_tmp_vreg_off(DisasContext *ctx, int regnum,
110 int num, bool alloc_ok)
111 {
112 intptr_t offset;
113
114 /* See if it is already allocated */
115 for (int i = 0; i < ctx->tmp_vregs_idx; i++) {
116 if (ctx->tmp_vregs_num[i] == regnum) {
117 return offsetof(CPUHexagonState, tmp_VRegs[i]);
118 }
119 }
120
121 g_assert(alloc_ok);
122 offset = offsetof(CPUHexagonState, tmp_VRegs[ctx->tmp_vregs_idx]);
123 for (int i = 0; i < num; i++) {
124 ctx->tmp_vregs_num[ctx->tmp_vregs_idx + i] = regnum++;
125 }
126 ctx->tmp_vregs_idx += num;
127 g_assert(ctx->tmp_vregs_idx <= VECTOR_TEMPS_MAX);
128 return offset;
129 }
130
131 static void gen_exception(int excp, uint32_t PC)
132 {
133 gen_helper_raise_exception(tcg_env, tcg_constant_i32(excp),
134 tcg_constant_i32(PC));
135 }
136
137 #ifndef CONFIG_USER_ONLY
138 static inline void gen_precise_exception(int excp, uint32_t PC)
139 {
140 tcg_gen_movi_i32(hex_cause_code, excp);
141 gen_exception(HEX_EVENT_PRECISE, PC);
142 }
143
144 static void gen_pcycle_counters(DisasContext *ctx)
145 {
146 if (ctx->pcycle_enabled) {
147 tcg_gen_addi_i64(hex_cycle_count, hex_cycle_count, ctx->num_cycles);
148 }
149 }
150 #endif
151
152
153 static void gen_exec_counters(DisasContext *ctx)
154 {
155 tcg_gen_addi_tl(hex_gpr[HEX_REG_QEMU_PKT_CNT],
156 hex_gpr[HEX_REG_QEMU_PKT_CNT], ctx->num_packets);
157 tcg_gen_addi_tl(hex_gpr[HEX_REG_QEMU_INSN_CNT],
158 hex_gpr[HEX_REG_QEMU_INSN_CNT], ctx->num_insns);
159 tcg_gen_addi_tl(hex_gpr[HEX_REG_QEMU_HVX_CNT],
160 hex_gpr[HEX_REG_QEMU_HVX_CNT], ctx->num_hvx_insns);
161 #ifndef CONFIG_USER_ONLY
162 gen_pcycle_counters(ctx);
163 #endif
164 }
165
166 static bool use_goto_tb(DisasContext *ctx, target_ulong dest)
167 {
168 return translator_use_goto_tb(&ctx->base, dest);
169 }
170
171 static void gen_goto_tb(DisasContext *ctx, unsigned tb_slot_idx,
172 target_ulong dest, bool move_to_pc)
173 {
174 if (use_goto_tb(ctx, dest)) {
175 tcg_gen_goto_tb(tb_slot_idx);
176 if (move_to_pc) {
177 tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], dest);
178 }
179 tcg_gen_exit_tb(ctx->base.tb, tb_slot_idx);
180 } else {
181 if (move_to_pc) {
182 tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], dest);
183 }
184 tcg_gen_lookup_and_goto_ptr();
185 }
186 }
187
188 static bool need_next_PC(DisasContext *ctx);
189
190 static void gen_end_tb(DisasContext *ctx)
191 {
192 gen_exec_counters(ctx);
193
194 if (ctx->need_next_pc) {
195 tcg_gen_mov_tl(hex_gpr[HEX_REG_PC], hex_next_PC);
196 }
197
198 if (ctx->branch_cond != TCG_COND_NEVER) {
199 if (ctx->branch_cond != TCG_COND_ALWAYS) {
200 TCGLabel *skip = gen_new_label();
201 tcg_gen_brcondi_tl(ctx->branch_cond, ctx->branch_taken, 1, skip);
202 gen_goto_tb(ctx, 0, ctx->branch_dest, true);
203 gen_set_label(skip);
204 gen_goto_tb(ctx, 1, ctx->next_PC, false);
205 } else {
206 gen_goto_tb(ctx, 0, ctx->branch_dest, true);
207 }
208 } else if (ctx->is_tight_loop &&
209 ctx->pkt.insn[ctx->pkt.num_insns - 1].opcode == J2_endloop0) {
210 /*
211 * When we're in a tight loop, we defer the endloop0 processing
212 * to take advantage of direct block chaining
213 */
214 TCGLabel *skip = gen_new_label();
215 tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC0], 1, skip);
216 tcg_gen_subi_tl(hex_gpr[HEX_REG_LC0], hex_gpr[HEX_REG_LC0], 1);
217 gen_goto_tb(ctx, 0, ctx->base.tb->pc, true);
218 gen_set_label(skip);
219 gen_goto_tb(ctx, 1, ctx->next_PC, false);
220 } else {
221 tcg_gen_lookup_and_goto_ptr();
222 }
223
224 ctx->base.is_jmp = DISAS_NORETURN;
225 }
226
227 void hex_gen_exception_end_tb(DisasContext *ctx, int excp)
228 {
229 gen_exec_counters(ctx);
230 #ifdef CONFIG_USER_ONLY
231 gen_exception(excp, ctx->pkt.pc);
232 #else
233 gen_precise_exception(excp, ctx->pkt.pc);
234 #endif
235 ctx->base.is_jmp = DISAS_NORETURN;
236 }
237
238 /*
239 * Generate exception for decode failures. Unlike gen_exception_end_tb,
240 * this is used when decode fails before ctx->next_PC is initialized.
241 */
242 static void gen_exception_decode_fail(DisasContext *ctx, int nwords, int excp)
243 {
244 target_ulong fail_pc = ctx->base.pc_next + nwords * sizeof(uint32_t);
245
246 gen_exec_counters(ctx);
247 tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], fail_pc);
248 gen_exception(excp, fail_pc);
249 ctx->base.is_jmp = DISAS_NORETURN;
250 ctx->base.pc_next = fail_pc;
251 }
252
253 static int read_packet_words(CPUHexagonState *env, DisasContext *ctx,
254 uint32_t words[])
255 {
256 bool found_end = false;
257 int nwords, max_words;
258
259 memset(words, 0, PACKET_WORDS_MAX * sizeof(uint32_t));
260 for (nwords = 0; !found_end && nwords < PACKET_WORDS_MAX; nwords++) {
261 words[nwords] =
262 translator_ldl_end(env, &ctx->base,
263 ctx->base.pc_next + nwords * sizeof(uint32_t),
264 MO_LE);
265 found_end = is_packet_end(words[nwords]);
266 }
267 if (!found_end) {
268 /* Read too many words without finding the end */
269 return 0;
270 }
271
272 /* Check for page boundary crossing */
273 max_words = -(ctx->base.pc_next | TARGET_PAGE_MASK) / sizeof(uint32_t);
274 if (nwords > max_words) {
275 /* We can only cross a page boundary at the beginning of a TB */
276 g_assert(ctx->base.num_insns == 1);
277 }
278
279 return nwords;
280 }
281
282 static bool check_for_attrib(Packet *pkt, int attrib)
283 {
284 for (int i = 0; i < pkt->num_insns; i++) {
285 if (GET_ATTRIB(pkt->insn[i].opcode, attrib)) {
286 return true;
287 }
288 }
289 return false;
290 }
291
292 static bool check_for_opcode(Packet *pkt, uint16_t opcode)
293 {
294 for (int i = 0; i < pkt->num_insns; i++) {
295 if (pkt->insn[i].opcode == opcode) {
296 return true;
297 }
298 }
299 return false;
300 }
301
302 static bool need_slot_cancelled(Packet *pkt)
303 {
304 /* We only need slot_cancelled for conditional store instructions */
305 for (int i = 0; i < pkt->num_insns; i++) {
306 uint16_t opcode = pkt->insn[i].opcode;
307 if (GET_ATTRIB(opcode, A_CONDEXEC) &&
308 GET_ATTRIB(opcode, A_SCALAR_STORE)) {
309 return true;
310 }
311 }
312 return false;
313 }
314
315 #ifndef CONFIG_USER_ONLY
316 static bool sreg_write_ends_tb(int reg_num)
317 {
318 return reg_num == HEX_SREG_SSR ||
319 reg_num == HEX_SREG_STID ||
320 reg_num == HEX_SREG_IMASK ||
321 reg_num == HEX_SREG_IPENDAD ||
322 reg_num == HEX_SREG_BESTWAIT ||
323 reg_num == HEX_SREG_SCHEDCFG;
324 }
325
326 static bool has_sreg_write_ends_tb(Packet const *pkt)
327 {
328 for (int i = 0; i < pkt->num_insns; i++) {
329 Insn const *insn = &pkt->insn[i];
330 uint16_t opcode = insn->opcode;
331 if (opcode == Y2_tfrsrcr) {
332 /* Write to a single sreg */
333 int reg_num = insn->regno[0];
334 if (sreg_write_ends_tb(reg_num)) {
335 return true;
336 }
337 } else if (opcode == Y4_tfrspcp) {
338 /* Write to a sreg pair */
339 int reg_num = insn->regno[0];
340 if (sreg_write_ends_tb(reg_num)) {
341 return true;
342 }
343 if (sreg_write_ends_tb(reg_num + 1)) {
344 return true;
345 }
346 }
347 }
348 return false;
349 }
350 #endif
351
352 static bool pkt_ends_tb(Packet *pkt)
353 {
354 if (pkt->pkt_has_cof) {
355 return true;
356 }
357 #ifndef CONFIG_USER_ONLY
358 /* System mode instructions that end TLB */
359 if (check_for_opcode(pkt, Y2_swi) ||
360 check_for_opcode(pkt, Y2_cswi) ||
361 check_for_opcode(pkt, Y2_ciad) ||
362 check_for_opcode(pkt, Y4_siad) ||
363 check_for_opcode(pkt, Y2_wait) ||
364 check_for_opcode(pkt, Y2_resume) ||
365 check_for_opcode(pkt, Y2_iassignw) ||
366 check_for_opcode(pkt, Y2_setimask) ||
367 check_for_opcode(pkt, Y4_nmi) ||
368 check_for_opcode(pkt, Y2_setprio) ||
369 check_for_opcode(pkt, Y2_start) ||
370 check_for_opcode(pkt, Y2_stop) ||
371 check_for_opcode(pkt, Y2_k0lock) ||
372 check_for_opcode(pkt, Y2_k0unlock) ||
373 check_for_opcode(pkt, Y2_tlblock) ||
374 check_for_opcode(pkt, Y2_tlbunlock) ||
375 check_for_opcode(pkt, Y2_break) ||
376 check_for_opcode(pkt, Y2_isync) ||
377 check_for_opcode(pkt, Y2_syncht) ||
378 check_for_opcode(pkt, Y2_tlbp) ||
379 check_for_opcode(pkt, Y2_tlbw) ||
380 check_for_opcode(pkt, Y5_ctlbw) ||
381 check_for_opcode(pkt, Y5_tlbasidi)) {
382 return true;
383 }
384
385 /*
386 * Check for sreg writes that would end the TB
387 */
388 if (check_for_attrib(pkt, A_IMPLICIT_WRITES_SSR)) {
389 return true;
390 }
391 if (has_sreg_write_ends_tb(pkt)) {
392 return true;
393 }
394 #endif
395 return false;
396 }
397
398
399 static bool need_next_PC(DisasContext *ctx)
400 {
401 Packet *pkt = &ctx->pkt;
402 if (pkt->pkt_has_cof || ctx->pkt_ends_tb) {
403 for (int i = 0; i < pkt->num_insns; i++) {
404 uint16_t opcode = pkt->insn[i].opcode;
405 if ((GET_ATTRIB(opcode, A_CONDEXEC) && GET_ATTRIB(opcode, A_COF)) ||
406 GET_ATTRIB(opcode, A_HWLOOP0_END) ||
407 GET_ATTRIB(opcode, A_HWLOOP1_END)) {
408 return true;
409 }
410 }
411 }
412 /*
413 * We end the TB on some instructions that do not change the flow (for
414 * other reasons). In these cases, we must set pc too, as the insn won't
415 * do it themselves.
416 */
417 if (ctx->pkt_ends_tb && !check_for_attrib(pkt, A_COF)) {
418 return true;
419 }
420 return false;
421 }
422
423 /*
424 * The opcode_analyze functions mark most of the writes in a packet
425 * However, there are some implicit writes marked as attributes
426 * of the applicable instructions.
427 */
428 static void mark_implicit_reg_write(DisasContext *ctx, int attrib, int rnum)
429 {
430 uint16_t opcode = ctx->insn->opcode;
431 if (GET_ATTRIB(opcode, attrib)) {
432 bool is_predicated = GET_ATTRIB(opcode, A_CONDEXEC);
433
434 /* LC0/LC1 is conditionally written by endloop instructions */
435 if ((rnum == HEX_REG_LC0 || rnum == HEX_REG_LC1) &&
436 (opcode == J2_endloop0 ||
437 opcode == J2_endloop1 ||
438 opcode == J2_endloop01)) {
439 is_predicated = true;
440 }
441
442 ctx_log_reg_write(ctx, rnum, is_predicated);
443 }
444 }
445
446 static void mark_implicit_usr_write(DisasContext *ctx, int attrib)
447 {
448 uint16_t opcode = ctx->insn->opcode;
449 if (GET_ATTRIB(opcode, attrib)) {
450 ctx->implicit_usr_write = true;
451 }
452 }
453
454 #ifndef CONFIG_USER_ONLY
455 static void mark_implicit_sreg_write(DisasContext *ctx, int attrib, int snum)
456 {
457 uint16_t opcode = ctx->insn->opcode;
458 if (GET_ATTRIB(opcode, attrib)) {
459 ctx_log_sreg_write(ctx, snum);
460 }
461 }
462 #endif
463
464 static void mark_implicit_reg_writes(DisasContext *ctx)
465 {
466 mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_FP, HEX_REG_FP);
467 mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_SP, HEX_REG_SP);
468 mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_LR, HEX_REG_LR);
469 mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_LC0, HEX_REG_LC0);
470 mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_SA0, HEX_REG_SA0);
471 mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_LC1, HEX_REG_LC1);
472 mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_SA1, HEX_REG_SA1);
473
474 mark_implicit_usr_write(ctx, A_IMPLICIT_WRITES_USR);
475 mark_implicit_usr_write(ctx, A_FPOP);
476
477 #ifndef CONFIG_USER_ONLY
478 mark_implicit_sreg_write(ctx, A_IMPLICIT_WRITES_SGP0, HEX_SREG_SGP0);
479 mark_implicit_sreg_write(ctx, A_IMPLICIT_WRITES_SGP1, HEX_SREG_SGP1);
480 mark_implicit_sreg_write(ctx, A_IMPLICIT_WRITES_SSR, HEX_SREG_SSR);
481 #endif
482 }
483
484 static void mark_implicit_pred_write(DisasContext *ctx, int attrib, int pnum)
485 {
486 if (GET_ATTRIB(ctx->insn->opcode, attrib)) {
487 ctx_log_pred_write(ctx, pnum);
488 }
489 }
490
491 static void mark_implicit_pred_writes(DisasContext *ctx)
492 {
493 mark_implicit_pred_write(ctx, A_IMPLICIT_WRITES_P0, 0);
494 mark_implicit_pred_write(ctx, A_IMPLICIT_WRITES_P1, 1);
495 mark_implicit_pred_write(ctx, A_IMPLICIT_WRITES_P2, 2);
496 mark_implicit_pred_write(ctx, A_IMPLICIT_WRITES_P3, 3);
497 }
498
499 static bool pkt_raises_exception(Packet *pkt)
500 {
501 if (check_for_attrib(pkt, A_LOAD) ||
502 check_for_attrib(pkt, A_STORE)) {
503 return true;
504 }
505 return false;
506 }
507
508 static bool need_commit(DisasContext *ctx)
509 {
510 /*
511 * If the short-circuit property is set to false, we'll always do the commit
512 */
513 if (!ctx->short_circuit) {
514 return true;
515 }
516
517 if (pkt_raises_exception(&ctx->pkt)) {
518 return true;
519 }
520
521 /* Registers with immutability flags require new_value */
522 for (int i = 0; i < ctx->reg_log_idx; i++) {
523 int rnum = ctx->reg_log[i];
524 if (reg_immut_masks[rnum]) {
525 return true;
526 }
527 }
528
529 if (ctx->read_after_write || ctx->has_hvx_overlap) {
530 return true;
531 }
532
533 return false;
534 }
535
536 static void mark_implicit_pred_read(DisasContext *ctx, int attrib, int pnum)
537 {
538 if (GET_ATTRIB(ctx->insn->opcode, attrib)) {
539 ctx_log_pred_read(ctx, pnum);
540 }
541 }
542
543 static void mark_implicit_pred_reads(DisasContext *ctx)
544 {
545 mark_implicit_pred_read(ctx, A_IMPLICIT_READS_P0, 0);
546 mark_implicit_pred_read(ctx, A_IMPLICIT_READS_P1, 1);
547 mark_implicit_pred_read(ctx, A_IMPLICIT_READS_P3, 2);
548 mark_implicit_pred_read(ctx, A_IMPLICIT_READS_P3, 3);
549 }
550
551 static void mark_implicit_reads(DisasContext *ctx)
552 {
553 mark_implicit_pred_reads(ctx);
554 }
555
556 static void mark_implicit_writes(DisasContext *ctx)
557 {
558 mark_implicit_reg_writes(ctx);
559 mark_implicit_pred_writes(ctx);
560 }
561
562 static void analyze_packet(DisasContext *ctx)
563 {
564 ctx->read_after_write = false;
565 ctx->has_hvx_overlap = false;
566 for (int i = 0; i < ctx->pkt.num_insns; i++) {
567 Insn *insn = &ctx->pkt.insn[i];
568 ctx->insn = insn;
569 if (opcode_analyze[insn->opcode]) {
570 opcode_analyze[insn->opcode](ctx);
571 }
572 }
573
574 ctx->need_commit = need_commit(ctx);
575 }
576
577 static void gen_start_packet(DisasContext *ctx)
578 {
579 Packet *pkt = &ctx->pkt;
580 target_ulong next_PC = (check_for_opcode(pkt, Y2_k0lock) ||
581 check_for_opcode(pkt, Y2_tlblock)) ?
582 ctx->base.pc_next :
583 ctx->base.pc_next + pkt->encod_pkt_size_in_bytes;
584 int i;
585
586 /* Clear out the disassembly context */
587 ctx->next_PC = next_PC;
588 ctx->reg_log_idx = 0;
589 bitmap_zero(ctx->regs_written, TOTAL_PER_THREAD_REGS);
590 bitmap_zero(ctx->predicated_regs, TOTAL_PER_THREAD_REGS);
591 #ifndef CONFIG_USER_ONLY
592 ctx->greg_log_idx = 0;
593 ctx->sreg_log_idx = 0;
594 #endif
595 ctx->preg_log_idx = 0;
596 bitmap_zero(ctx->pregs_written, NUM_PREGS);
597 ctx->future_vregs_idx = 0;
598 ctx->tmp_vregs_idx = 0;
599 ctx->vreg_log_idx = 0;
600 bitmap_zero(ctx->vregs_written, NUM_VREGS);
601 bitmap_zero(ctx->vregs_updated_tmp, NUM_VREGS);
602 bitmap_zero(ctx->vregs_updated, NUM_VREGS);
603 bitmap_zero(ctx->vregs_select, NUM_VREGS);
604 bitmap_zero(ctx->predicated_future_vregs, NUM_VREGS);
605 bitmap_zero(ctx->predicated_tmp_vregs, NUM_VREGS);
606 bitmap_zero(ctx->qregs_written, NUM_QREGS);
607 ctx->qreg_log_idx = 0;
608 for (i = 0; i < STORES_MAX; i++) {
609 ctx->store_width[i] = 0;
610 }
611 ctx->s1_store_processed = false;
612 ctx->pre_commit = true;
613 for (i = 0; i < TOTAL_PER_THREAD_REGS; i++) {
614 ctx->new_value[i] = NULL;
615 }
616 for (i = 0; i < NUM_PREGS; i++) {
617 ctx->new_pred_value[i] = NULL;
618 }
619
620 analyze_packet(ctx);
621
622 /*
623 * pregs_written is used both in the analyze phase as well as the code
624 * gen phase, so clear it again.
625 */
626 bitmap_zero(ctx->pregs_written, NUM_PREGS);
627 #ifndef CONFIG_USER_ONLY
628 for (i = 0; i < HEX_SREG_GLB_START; i++) {
629 ctx->t_sreg_new_value[i] = NULL;
630 }
631 for (i = 0; i < ctx->sreg_log_idx; i++) {
632 int reg_num = ctx->sreg_log[i];
633 if (reg_num < HEX_SREG_GLB_START) {
634 ctx->t_sreg_new_value[reg_num] = tcg_temp_new();
635 tcg_gen_mov_tl(ctx->t_sreg_new_value[reg_num],
636 hex_t_sreg[reg_num]);
637 }
638 }
639 for (i = 0; i < NUM_GREGS; i++) {
640 ctx->greg_new_value[i] = NULL;
641 }
642 for (i = 0; i < ctx->greg_log_idx; i++) {
643 int reg_num = ctx->greg_log[i];
644 ctx->greg_new_value[reg_num] = tcg_temp_new();
645 }
646 #endif
647
648 /* Initialize the runtime state for packet semantics */
649 if (need_slot_cancelled(&ctx->pkt)) {
650 tcg_gen_movi_tl(hex_slot_cancelled, 0);
651 }
652 ctx->branch_taken = NULL;
653 if (ctx->pkt.pkt_has_cof) {
654 ctx->branch_taken = tcg_temp_new();
655 }
656 if (ctx->pkt.pkt_has_multi_cof) {
657 tcg_gen_movi_tl(ctx->branch_taken, 0);
658 }
659 ctx->pkt_ends_tb = pkt_ends_tb(&ctx->pkt);
660 ctx->need_next_pc = need_next_PC(ctx);
661 if (ctx->need_next_pc) {
662 tcg_gen_movi_tl(hex_next_PC, next_PC);
663 }
664
665 /* Preload the predicated registers into get_result_gpr(ctx, i) */
666 if (ctx->need_commit &&
667 !bitmap_empty(ctx->predicated_regs, TOTAL_PER_THREAD_REGS)) {
668 i = find_first_bit(ctx->predicated_regs, TOTAL_PER_THREAD_REGS);
669 while (i < TOTAL_PER_THREAD_REGS) {
670 tcg_gen_mov_tl(get_result_gpr(ctx, i), hex_gpr[i]);
671 i = find_next_bit(ctx->predicated_regs, TOTAL_PER_THREAD_REGS,
672 i + 1);
673 }
674 }
675
676 /* Preload usr to new_value_usr */
677 if (ctx->need_commit && ctx->implicit_usr_write &&
678 !test_bit(HEX_REG_USR, ctx->regs_written)) {
679 tcg_gen_mov_tl(hex_new_value_usr, hex_gpr[HEX_REG_USR]);
680 }
681
682 /*
683 * Preload the predicated pred registers into ctx->new_pred_value[pred_num]
684 * Only endloop instructions conditionally write to pred registers
685 */
686 if (ctx->need_commit && ctx->pkt.pkt_has_endloop) {
687 for (i = 0; i < ctx->preg_log_idx; i++) {
688 int pred_num = ctx->preg_log[i];
689 ctx->new_pred_value[pred_num] = tcg_temp_new();
690 tcg_gen_mov_tl(ctx->new_pred_value[pred_num], hex_pred[pred_num]);
691 }
692 }
693
694 /* Preload the predicated HVX registers into future_VRegs and tmp_VRegs */
695 if (!bitmap_empty(ctx->predicated_future_vregs, NUM_VREGS)) {
696 i = find_first_bit(ctx->predicated_future_vregs, NUM_VREGS);
697 while (i < NUM_VREGS) {
698 const intptr_t VdV_off =
699 ctx_future_vreg_off(ctx, i, 1, true);
700 intptr_t src_off = offsetof(CPUHexagonState, VRegs[i]);
701 tcg_gen_gvec_mov(MO_64, VdV_off,
702 src_off,
703 sizeof(MMVector),
704 sizeof(MMVector));
705 i = find_next_bit(ctx->predicated_future_vregs, NUM_VREGS, i + 1);
706 }
707 }
708 if (!bitmap_empty(ctx->predicated_tmp_vregs, NUM_VREGS)) {
709 i = find_first_bit(ctx->predicated_tmp_vregs, NUM_VREGS);
710 while (i < NUM_VREGS) {
711 const intptr_t VdV_off =
712 ctx_tmp_vreg_off(ctx, i, 1, true);
713 intptr_t src_off = offsetof(CPUHexagonState, VRegs[i]);
714 tcg_gen_gvec_mov(MO_64, VdV_off,
715 src_off,
716 sizeof(MMVector),
717 sizeof(MMVector));
718 i = find_next_bit(ctx->predicated_tmp_vregs, NUM_VREGS, i + 1);
719 }
720 }
721 }
722
723 bool is_gather_store_insn(DisasContext *ctx)
724 {
725 if (GET_ATTRIB(ctx->insn->opcode, A_CVI_NEW) &&
726 ctx->insn->new_value_producer_slot == 1) {
727 /* Look for gather instruction */
728 for (int i = 0; i < ctx->pkt.num_insns; i++) {
729 Insn *in = &ctx->pkt.insn[i];
730 if (GET_ATTRIB(in->opcode, A_CVI_GATHER) && in->slot == 1) {
731 return true;
732 }
733 }
734 }
735 return false;
736 }
737
738 static void mark_store_width(DisasContext *ctx)
739 {
740 uint16_t opcode = ctx->insn->opcode;
741 uint32_t slot = ctx->insn->slot;
742 uint8_t width = 0;
743
744 if (GET_ATTRIB(opcode, A_SCALAR_STORE)) {
745 if (GET_ATTRIB(opcode, A_MEMSIZE_0B)) {
746 return;
747 }
748 if (GET_ATTRIB(opcode, A_MEMSIZE_1B)) {
749 width |= 1;
750 }
751 if (GET_ATTRIB(opcode, A_MEMSIZE_2B)) {
752 width |= 2;
753 }
754 if (GET_ATTRIB(opcode, A_MEMSIZE_4B)) {
755 width |= 4;
756 }
757 if (GET_ATTRIB(opcode, A_MEMSIZE_8B)) {
758 width |= 8;
759 }
760 tcg_debug_assert(is_power_of_2(width));
761 ctx->store_width[slot] = width;
762 }
763 }
764
765 static void gen_insn(DisasContext *ctx)
766 {
767 if (ctx->insn->generate) {
768 ctx->insn->generate(ctx);
769 mark_store_width(ctx);
770 } else {
771 hex_gen_exception_end_tb(ctx, HEX_CAUSE_INVALID_OPCODE);
772 }
773 }
774
775 /*
776 * Helpers for generating the packet commit
777 */
778 static void gen_reg_writes(DisasContext *ctx)
779 {
780 int i;
781
782 /* Early exit if not needed */
783 if (!ctx->need_commit) {
784 return;
785 }
786
787 for (i = 0; i < ctx->reg_log_idx; i++) {
788 int reg_num = ctx->reg_log[i];
789
790 tcg_gen_mov_tl(hex_gpr[reg_num], get_result_gpr(ctx, reg_num));
791
792 /*
793 * ctx->is_tight_loop is set when SA0 points to the beginning of the TB.
794 * If we write to SA0, we have to turn off tight loop handling.
795 */
796 if (reg_num == HEX_REG_SA0) {
797 ctx->is_tight_loop = false;
798 }
799 }
800
801 if (ctx->implicit_usr_write && !test_bit(HEX_REG_USR, ctx->regs_written)) {
802 tcg_gen_mov_tl(hex_gpr[HEX_REG_USR], hex_new_value_usr);
803 }
804 }
805
806 #ifndef CONFIG_USER_ONLY
807 static void gen_greg_writes(DisasContext *ctx)
808 {
809 int i;
810
811 for (i = 0; i < ctx->greg_log_idx; i++) {
812 int reg_num = ctx->greg_log[i];
813
814 tcg_gen_mov_tl(hex_greg[reg_num], ctx->greg_new_value[reg_num]);
815 }
816 }
817
818
819 static void gen_sreg_writes(DisasContext *ctx)
820 {
821 int i;
822
823 TCGv_i32 old_reg = tcg_temp_new_i32();
824 for (i = 0; i < ctx->sreg_log_idx; i++) {
825 int reg_num = ctx->sreg_log[i];
826
827 if (reg_num == HEX_SREG_SSR) {
828 tcg_gen_mov_tl(old_reg, hex_t_sreg[reg_num]);
829 tcg_gen_mov_tl(hex_t_sreg[reg_num], ctx->t_sreg_new_value[reg_num]);
830 gen_helper_modify_ssr(tcg_env, ctx->t_sreg_new_value[reg_num],
831 old_reg);
832 } else if ((reg_num == HEX_SREG_STID) ||
833 (reg_num == HEX_SREG_IMASK) ||
834 (reg_num == HEX_SREG_IPENDAD)) {
835 if (ctx->need_commit && reg_num < HEX_SREG_GLB_START) {
836 tcg_gen_mov_tl(hex_t_sreg[reg_num],
837 ctx->t_sreg_new_value[reg_num]);
838 }
839 gen_helper_pending_interrupt(tcg_env);
840 } else if ((reg_num == HEX_SREG_BESTWAIT) ||
841 (reg_num == HEX_SREG_SCHEDCFG)) {
842 gen_helper_resched(tcg_env);
843 } else if (ctx->need_commit && reg_num < HEX_SREG_GLB_START) {
844 tcg_gen_mov_tl(hex_t_sreg[reg_num], ctx->t_sreg_new_value[reg_num]);
845 }
846 }
847 }
848 #endif
849
850 static void gen_pred_writes(DisasContext *ctx)
851 {
852 /* Early exit if not needed or the log is empty */
853 if (!ctx->need_commit || !ctx->preg_log_idx) {
854 return;
855 }
856
857 for (int i = 0; i < ctx->preg_log_idx; i++) {
858 int pred_num = ctx->preg_log[i];
859 tcg_gen_mov_tl(hex_pred[pred_num], ctx->new_pred_value[pred_num]);
860 }
861 }
862
863 static bool slot_is_predicated(Packet *pkt, int slot_num)
864 {
865 for (int i = 0; i < pkt->num_insns; i++) {
866 if (pkt->insn[i].slot == slot_num) {
867 return GET_ATTRIB(pkt->insn[i].opcode, A_CONDEXEC);
868 }
869 }
870 /* If we get to here, we didn't find an instruction in the requested slot */
871 g_assert_not_reached();
872 }
873
874 void process_store(DisasContext *ctx, int slot_num)
875 {
876 bool is_predicated = slot_is_predicated(&ctx->pkt, slot_num);
877 TCGLabel *label_end = NULL;
878
879 /*
880 * We may have already processed this store
881 * See CHECK_NOSHUF in macros.h
882 */
883 if (slot_num == 1 && ctx->s1_store_processed) {
884 return;
885 }
886 ctx->s1_store_processed = true;
887
888 if (is_predicated) {
889 TCGv cancelled = tcg_temp_new();
890 label_end = gen_new_label();
891
892 /* Don't do anything if the slot was cancelled */
893 tcg_gen_extract_tl(cancelled, hex_slot_cancelled, slot_num, 1);
894 tcg_gen_brcondi_tl(TCG_COND_NE, cancelled, 0, label_end);
895 }
896 {
897 TCGv address = tcg_temp_new();
898 tcg_gen_mov_tl(address, hex_store_addr[slot_num]);
899
900 /*
901 * If we know the width from the DisasContext, we can
902 * generate much cleaner code.
903 * Unfortunately, not all instructions execute the fSTORE
904 * macro during code generation. Anything that uses the
905 * generic helper will have this problem. Instructions
906 * that use fWRAP to generate proper TCG code will be OK.
907 */
908 switch (ctx->store_width[slot_num]) {
909 case 1:
910 tcg_gen_qemu_st_tl(hex_store_val32[slot_num],
911 hex_store_addr[slot_num],
912 ctx->mem_idx, MO_UB);
913 break;
914 case 2:
915 tcg_gen_qemu_st_tl(hex_store_val32[slot_num],
916 hex_store_addr[slot_num],
917 ctx->mem_idx, MO_LE | MO_UW | MO_ALIGN);
918 break;
919 case 4:
920 tcg_gen_qemu_st_tl(hex_store_val32[slot_num],
921 hex_store_addr[slot_num],
922 ctx->mem_idx, MO_LE | MO_UL | MO_ALIGN);
923 break;
924 case 8:
925 tcg_gen_qemu_st_i64(hex_store_val64[slot_num],
926 hex_store_addr[slot_num],
927 ctx->mem_idx, MO_LE | MO_UQ | MO_ALIGN);
928 break;
929 default:
930 {
931 /*
932 * If we get to here, we don't know the width at
933 * TCG generation time, we'll use a helper to
934 * avoid branching based on the width at runtime.
935 */
936 TCGv slot = tcg_constant_tl(slot_num);
937 gen_helper_commit_store(tcg_env, slot);
938 }
939 }
940 }
941 if (is_predicated) {
942 gen_set_label(label_end);
943 }
944 }
945
946 static void process_store_log(DisasContext *ctx)
947 {
948 /*
949 * When a packet has two stores, the hardware processes
950 * slot 1 and then slot 0. This will be important when
951 * the memory accesses overlap.
952 */
953 if (ctx->pkt.pkt_has_scalar_store_s1) {
954 g_assert(!ctx->pkt.pkt_has_dczeroa);
955 process_store(ctx, 1);
956 }
957 if (ctx->pkt.pkt_has_scalar_store_s0) {
958 g_assert(!ctx->pkt.pkt_has_dczeroa);
959 process_store(ctx, 0);
960 }
961 }
962
963 /* Zero out a 32-bit cache line */
964 static void process_dczeroa(DisasContext *ctx)
965 {
966 if (ctx->pkt.pkt_has_dczeroa) {
967 /* Store 32 bytes of zero starting at (addr & ~0x1f) */
968 TCGv addr = tcg_temp_new();
969 TCGv_i64 zero = tcg_constant_i64(0);
970
971 tcg_gen_andi_tl(addr, ctx->dczero_addr, ~0x1f);
972 tcg_gen_qemu_st_i64(zero, addr, ctx->mem_idx, MO_UQ);
973 tcg_gen_addi_tl(addr, addr, 8);
974 tcg_gen_qemu_st_i64(zero, addr, ctx->mem_idx, MO_UQ);
975 tcg_gen_addi_tl(addr, addr, 8);
976 tcg_gen_qemu_st_i64(zero, addr, ctx->mem_idx, MO_UQ);
977 tcg_gen_addi_tl(addr, addr, 8);
978 tcg_gen_qemu_st_i64(zero, addr, ctx->mem_idx, MO_UQ);
979 }
980 }
981
982 static bool pkt_has_hvx_store(Packet *pkt)
983 {
984 int i;
985 for (i = 0; i < pkt->num_insns; i++) {
986 int opcode = pkt->insn[i].opcode;
987 if (GET_ATTRIB(opcode, A_CVI) && GET_ATTRIB(opcode, A_STORE)) {
988 return true;
989 }
990 }
991 return false;
992 }
993
994 static void gen_commit_hvx(DisasContext *ctx)
995 {
996 int i;
997
998 /* Early exit if not needed */
999 if (!ctx->need_commit) {
1000 g_assert(!pkt_has_hvx_store(&ctx->pkt));
1001 return;
1002 }
1003
1004 /*
1005 * for (i = 0; i < ctx->vreg_log_idx; i++) {
1006 * int rnum = ctx->vreg_log[i];
1007 * env->VRegs[rnum] = env->future_VRegs[rnum];
1008 * }
1009 */
1010 for (i = 0; i < ctx->vreg_log_idx; i++) {
1011 int rnum = ctx->vreg_log[i];
1012 intptr_t dstoff = offsetof(CPUHexagonState, VRegs[rnum]);
1013 intptr_t srcoff = ctx_future_vreg_off(ctx, rnum, 1, false);
1014 size_t size = sizeof(MMVector);
1015
1016 tcg_gen_gvec_mov(MO_64, dstoff, srcoff, size, size);
1017 }
1018
1019 /*
1020 * for (i = 0; i < ctx->qreg_log_idx; i++) {
1021 * int rnum = ctx->qreg_log[i];
1022 * env->QRegs[rnum] = env->future_QRegs[rnum];
1023 * }
1024 */
1025 for (i = 0; i < ctx->qreg_log_idx; i++) {
1026 int rnum = ctx->qreg_log[i];
1027 intptr_t dstoff = offsetof(CPUHexagonState, QRegs[rnum]);
1028 intptr_t srcoff = offsetof(CPUHexagonState, future_QRegs[rnum]);
1029 size_t size = sizeof(MMQReg);
1030
1031 tcg_gen_gvec_mov(MO_64, dstoff, srcoff, size, size);
1032 }
1033
1034 if (pkt_has_hvx_store(&ctx->pkt)) {
1035 gen_helper_commit_hvx_stores(tcg_env);
1036 }
1037 }
1038
1039 #define PCYCLES_PER_PACKET 1
1040
1041 static void update_exec_counters(DisasContext *ctx)
1042 {
1043 int num_real_insns = 0;
1044 int num_hvx_insns = 0;
1045
1046 for (int i = 0; i < ctx->pkt.num_insns; i++) {
1047 if (!ctx->pkt.insn[i].is_endloop &&
1048 !ctx->pkt.insn[i].part1 &&
1049 !GET_ATTRIB(ctx->pkt.insn[i].opcode, A_IT_NOP)) {
1050 num_real_insns++;
1051 }
1052 if (GET_ATTRIB(ctx->pkt.insn[i].opcode, A_CVI)) {
1053 num_hvx_insns++;
1054 }
1055 }
1056
1057 ctx->num_packets++;
1058 ctx->num_insns += num_real_insns;
1059 ctx->num_hvx_insns += num_hvx_insns;
1060 ctx->num_cycles += PCYCLES_PER_PACKET;
1061 }
1062
1063 static void gen_commit_packet(DisasContext *ctx)
1064 {
1065 /*
1066 * If there is more than one store in a packet, make sure they are all OK
1067 * before proceeding with the rest of the packet commit.
1068 *
1069 * dczeroa has to be the only store operation in the packet, so we go
1070 * ahead and process that first.
1071 *
1072 * When there is an HVX store, there can also be a scalar store in either
1073 * slot 0 or slot1, so we create a mask for the helper to indicate what
1074 * work to do.
1075 *
1076 * When there are two scalar stores, we probe the one in slot 0.
1077 *
1078 * Note that we don't call the probe helper for packets with only one
1079 * store. Therefore, we call process_store_log before anything else
1080 * involved in committing the packet.
1081 */
1082 bool has_store_s0 = ctx->pkt.pkt_has_scalar_store_s0;
1083 bool has_store_s1 =
1084 (ctx->pkt.pkt_has_scalar_store_s1 && !ctx->s1_store_processed);
1085 bool has_hvx_store = pkt_has_hvx_store(&ctx->pkt);
1086 if (ctx->pkt.pkt_has_dczeroa) {
1087 /*
1088 * The dczeroa will be the store in slot 0, check that we don't have
1089 * a store in slot 1 or an HVX store.
1090 */
1091 g_assert(!has_store_s1 && !has_hvx_store);
1092 process_dczeroa(ctx);
1093 } else if (has_hvx_store) {
1094 if (!has_store_s0 && !has_store_s1) {
1095 TCGv mem_idx = tcg_constant_tl(ctx->mem_idx);
1096 gen_helper_probe_hvx_stores(tcg_env, mem_idx);
1097 } else {
1098 int mask = 0;
1099
1100 if (has_store_s0) {
1101 mask =
1102 FIELD_DP32(mask, PROBE_PKT_SCALAR_HVX_STORES, HAS_ST0, 1);
1103 }
1104 if (has_store_s1) {
1105 mask =
1106 FIELD_DP32(mask, PROBE_PKT_SCALAR_HVX_STORES, HAS_ST1, 1);
1107 }
1108 if (has_hvx_store) {
1109 mask =
1110 FIELD_DP32(mask, PROBE_PKT_SCALAR_HVX_STORES,
1111 HAS_HVX_STORES, 1);
1112 }
1113 if (has_store_s0 && slot_is_predicated(&ctx->pkt, 0)) {
1114 mask = FIELD_DP32(mask, PROBE_PKT_SCALAR_HVX_STORES, S0_IS_PRED,
1115 1);
1116 }
1117 if (has_store_s1 && slot_is_predicated(&ctx->pkt, 1)) {
1118 mask =
1119 FIELD_DP32(mask, PROBE_PKT_SCALAR_HVX_STORES,
1120 S1_IS_PRED, 1);
1121 }
1122 mask = FIELD_DP32(mask, PROBE_PKT_SCALAR_HVX_STORES, MMU_IDX,
1123 ctx->mem_idx);
1124 gen_helper_probe_pkt_scalar_hvx_stores(tcg_env,
1125 tcg_constant_tl(mask));
1126 }
1127 } else if (has_store_s0 && has_store_s1) {
1128 /*
1129 * process_store_log will execute the slot 1 store first,
1130 * so we only have to probe the store in slot 0
1131 */
1132 int args = 0;
1133 args =
1134 FIELD_DP32(args, PROBE_PKT_SCALAR_STORE_S0, MMU_IDX, ctx->mem_idx);
1135 if (slot_is_predicated(&ctx->pkt, 0)) {
1136 args =
1137 FIELD_DP32(args, PROBE_PKT_SCALAR_STORE_S0, IS_PREDICATED, 1);
1138 }
1139 TCGv args_tcgv = tcg_constant_tl(args);
1140 gen_helper_probe_pkt_scalar_store_s0(tcg_env, args_tcgv);
1141 }
1142
1143 process_store_log(ctx);
1144
1145 gen_reg_writes(ctx);
1146 #ifndef CONFIG_USER_ONLY
1147 gen_greg_writes(ctx);
1148 gen_sreg_writes(ctx);
1149 #endif
1150 gen_pred_writes(ctx);
1151 if (ctx->pkt.pkt_has_hvx) {
1152 gen_commit_hvx(ctx);
1153 }
1154 update_exec_counters(ctx);
1155
1156 if (ctx->pkt.vhist_insn != NULL) {
1157 ctx->pre_commit = false;
1158 ctx->insn = ctx->pkt.vhist_insn;
1159 ctx->pkt.vhist_insn->generate(ctx);
1160 }
1161
1162 if (ctx->pkt_ends_tb || ctx->base.is_jmp == DISAS_NORETURN) {
1163 gen_end_tb(ctx);
1164 }
1165 }
1166
1167 static void decode_and_translate_packet(CPUHexagonState *env, DisasContext *ctx)
1168 {
1169 uint32_t words[PACKET_WORDS_MAX];
1170 int nwords, words_read;
1171 int i;
1172
1173 nwords = read_packet_words(env, ctx, words);
1174 if (!nwords) {
1175 gen_exception_decode_fail(ctx, 0, HEX_CAUSE_INVALID_PACKET);
1176 return;
1177 }
1178
1179 words_read = decode_packet(ctx, nwords, words, &ctx->pkt, false);
1180 if (words_read > 0) {
1181 ctx->pkt.pc = ctx->base.pc_next;
1182 if (ctx->pkt.pkt_has_write_conflict) {
1183 gen_exception_decode_fail(ctx, words_read,
1184 HEX_CAUSE_REG_WRITE_CONFLICT);
1185 return;
1186 }
1187 gen_start_packet(ctx);
1188 for (i = 0; i < ctx->pkt.num_insns; i++) {
1189 ctx->insn = &ctx->pkt.insn[i];
1190 gen_insn(ctx);
1191 }
1192 gen_commit_packet(ctx);
1193 ctx->base.pc_next += ctx->pkt.encod_pkt_size_in_bytes;
1194 } else {
1195 gen_exception_decode_fail(ctx, nwords, HEX_CAUSE_INVALID_PACKET);
1196 }
1197 }
1198
1199 static void hexagon_tr_init_disas_context(DisasContextBase *dcbase,
1200 CPUState *cs)
1201 {
1202 DisasContext *ctx = container_of(dcbase, DisasContext, base);
1203 HexagonCPU *hex_cpu = env_archcpu(cpu_env(cs));
1204 uint32_t hex_flags = dcbase->tb->flags;
1205
1206 ctx->mem_idx = FIELD_EX32(hex_flags, TB_FLAGS, MMU_INDEX);
1207 ctx->num_packets = 0;
1208 ctx->num_insns = 0;
1209 ctx->num_hvx_insns = 0;
1210 ctx->branch_cond = TCG_COND_NEVER;
1211 ctx->is_tight_loop = FIELD_EX32(hex_flags, TB_FLAGS, IS_TIGHT_LOOP);
1212 ctx->short_circuit = hex_cpu->cfg.short_circuit;
1213 ctx->hex_def = HEXAGON_CPU_GET_CLASS(hex_cpu)->hex_def;
1214 ctx->ieee_fp_extension = hex_cpu->cfg.ieee_fp_extension;
1215 #ifndef CONFIG_USER_ONLY
1216 ctx->num_cycles = 0;
1217 ctx->pcycle_enabled = FIELD_EX32(hex_flags, TB_FLAGS, PCYCLE_ENABLED);
1218 #endif
1219 }
1220
1221 static void hexagon_tr_tb_start(DisasContextBase *db, CPUState *cpu)
1222 {
1223 }
1224
1225 static void hexagon_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
1226 {
1227 DisasContext *ctx = container_of(dcbase, DisasContext, base);
1228
1229 tcg_gen_insn_start(ctx->base.pc_next, 0, 0);
1230 }
1231
1232 static bool pkt_crosses_page(CPUHexagonState *env, DisasContext *ctx)
1233 {
1234 target_ulong page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
1235 bool found_end = false;
1236 int nwords;
1237
1238 for (nwords = 0; !found_end && nwords < PACKET_WORDS_MAX; nwords++) {
1239 uint32_t word = translator_ldl_end(env, &ctx->base,
1240 ctx->base.pc_next
1241 + nwords * sizeof(uint32_t),
1242 MO_LE);
1243 found_end = is_packet_end(word);
1244 }
1245 uint32_t next_ptr = ctx->base.pc_next + nwords * sizeof(uint32_t);
1246 return found_end && next_ptr - page_start >= TARGET_PAGE_SIZE;
1247 }
1248
1249 static void hexagon_tr_translate_packet(DisasContextBase *dcbase, CPUState *cpu)
1250 {
1251 DisasContext *ctx = container_of(dcbase, DisasContext, base);
1252 CPUHexagonState *env = cpu_env(cpu);
1253
1254 decode_and_translate_packet(env, ctx);
1255
1256 if (ctx->base.is_jmp == DISAS_NEXT) {
1257 target_ulong page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
1258 target_ulong bytes_max = PACKET_WORDS_MAX * sizeof(target_ulong);
1259
1260 if (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE ||
1261 (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE - bytes_max &&
1262 pkt_crosses_page(env, ctx))) {
1263 ctx->base.is_jmp = DISAS_TOO_MANY;
1264 }
1265
1266 /*
1267 * The CPU log is used to compare against LLDB single stepping,
1268 * so end the TLB after every packet.
1269 */
1270 HexagonCPU *hex_cpu = env_archcpu(env);
1271 if (hex_cpu->cfg.lldb_compat && qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
1272 ctx->base.is_jmp = DISAS_TOO_MANY;
1273 }
1274 }
1275 }
1276
1277 static void hexagon_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
1278 {
1279 DisasContext *ctx = container_of(dcbase, DisasContext, base);
1280
1281 switch (ctx->base.is_jmp) {
1282 case DISAS_TOO_MANY:
1283 gen_exec_counters(ctx);
1284 tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], ctx->base.pc_next);
1285 tcg_gen_exit_tb(NULL, 0);
1286 break;
1287 case DISAS_NORETURN:
1288 break;
1289 default:
1290 g_assert_not_reached();
1291 }
1292 }
1293
1294 static const TranslatorOps hexagon_tr_ops = {
1295 .init_disas_context = hexagon_tr_init_disas_context,
1296 .tb_start = hexagon_tr_tb_start,
1297 .insn_start = hexagon_tr_insn_start,
1298 .translate_insn = hexagon_tr_translate_packet,
1299 .tb_stop = hexagon_tr_tb_stop,
1300 };
1301
1302 void hexagon_translate_code(CPUState *cs, TranslationBlock *tb,
1303 int *max_insns, vaddr pc, void *host_pc)
1304 {
1305 DisasContext ctx;
1306
1307 translator_loop(cs, tb, max_insns, pc, host_pc,
1308 &hexagon_tr_ops, &ctx.base,
1309 TCG_TYPE_VA);
1310 }
1311
1312 #define NAME_LEN 64
1313 static char store_addr_names[STORES_MAX][NAME_LEN];
1314 static char store_width_names[STORES_MAX][NAME_LEN];
1315 static char store_val32_names[STORES_MAX][NAME_LEN];
1316 static char store_val64_names[STORES_MAX][NAME_LEN];
1317 static char vstore_addr_names[VSTORES_MAX][NAME_LEN];
1318 static char vstore_size_names[VSTORES_MAX][NAME_LEN];
1319 static char vstore_pending_names[VSTORES_MAX][NAME_LEN];
1320
1321 void hexagon_translate_init(void)
1322 {
1323 int i;
1324
1325 opcode_init();
1326
1327 #ifndef CONFIG_USER_ONLY
1328 for (i = 0; i < NUM_GREGS; i++) {
1329 hex_greg[i] = tcg_global_mem_new_i32(tcg_env,
1330 offsetof(CPUHexagonState, greg[i]),
1331 hexagon_gregnames[i]);
1332 }
1333 for (i = 0; i < NUM_SREGS; i++) {
1334 if (i < HEX_SREG_GLB_START) {
1335 hex_t_sreg[i] = tcg_global_mem_new_i32(tcg_env,
1336 offsetof(CPUHexagonState, t_sreg[i]),
1337 hexagon_sregnames[i]);
1338 }
1339 }
1340 #endif
1341 for (i = 0; i < TOTAL_PER_THREAD_REGS; i++) {
1342 hex_gpr[i] = tcg_global_mem_new(tcg_env,
1343 offsetof(CPUHexagonState, gpr[i]),
1344 hexagon_regnames[i]);
1345 }
1346 hex_new_value_usr = tcg_global_mem_new(tcg_env,
1347 offsetof(CPUHexagonState, new_value_usr), "new_value_usr");
1348 hex_next_PC = tcg_global_mem_new(tcg_env,
1349 offsetof(CPUHexagonState, next_PC), "next_PC");
1350
1351 for (i = 0; i < NUM_PREGS; i++) {
1352 hex_pred[i] = tcg_global_mem_new(tcg_env,
1353 offsetof(CPUHexagonState, pred[i]),
1354 hexagon_prednames[i]);
1355 }
1356 hex_slot_cancelled = tcg_global_mem_new(tcg_env,
1357 offsetof(CPUHexagonState, slot_cancelled), "slot_cancelled");
1358 hex_llsc_addr = tcg_global_mem_new(tcg_env,
1359 offsetof(CPUHexagonState, llsc_addr), "llsc_addr");
1360 hex_llsc_val = tcg_global_mem_new(tcg_env,
1361 offsetof(CPUHexagonState, llsc_val), "llsc_val");
1362 hex_llsc_val_i64 = tcg_global_mem_new_i64(tcg_env,
1363 offsetof(CPUHexagonState, llsc_val_i64), "llsc_val_i64");
1364 #ifndef CONFIG_USER_ONLY
1365 hex_cause_code = tcg_global_mem_new_i32(tcg_env,
1366 offsetof(CPUHexagonState, cause_code), "cause_code");
1367 hex_cycle_count = tcg_global_mem_new_i64(tcg_env,
1368 offsetof(CPUHexagonState, t_cycle_count), "t_cycle_count");
1369 #endif
1370 for (i = 0; i < STORES_MAX; i++) {
1371 snprintf(store_addr_names[i], NAME_LEN, "store_addr_%d", i);
1372 hex_store_addr[i] = tcg_global_mem_new(tcg_env,
1373 offsetof(CPUHexagonState, mem_log_stores[i].va),
1374 store_addr_names[i]);
1375
1376 snprintf(store_width_names[i], NAME_LEN, "store_width_%d", i);
1377 hex_store_width[i] = tcg_global_mem_new_i32(tcg_env,
1378 offsetof(CPUHexagonState, mem_log_stores[i].width),
1379 store_width_names[i]);
1380
1381 snprintf(store_val32_names[i], NAME_LEN, "store_val32_%d", i);
1382 hex_store_val32[i] = tcg_global_mem_new(tcg_env,
1383 offsetof(CPUHexagonState, mem_log_stores[i].data32),
1384 store_val32_names[i]);
1385
1386 snprintf(store_val64_names[i], NAME_LEN, "store_val64_%d", i);
1387 hex_store_val64[i] = tcg_global_mem_new_i64(tcg_env,
1388 offsetof(CPUHexagonState, mem_log_stores[i].data64),
1389 store_val64_names[i]);
1390 }
1391 for (i = 0; i < VSTORES_MAX; i++) {
1392 snprintf(vstore_addr_names[i], NAME_LEN, "vstore_addr_%d", i);
1393 hex_vstore_addr[i] = tcg_global_mem_new(tcg_env,
1394 offsetof(CPUHexagonState, vstore[i].va),
1395 vstore_addr_names[i]);
1396
1397 snprintf(vstore_size_names[i], NAME_LEN, "vstore_size_%d", i);
1398 hex_vstore_size[i] = tcg_global_mem_new(tcg_env,
1399 offsetof(CPUHexagonState, vstore[i].size),
1400 vstore_size_names[i]);
1401
1402 snprintf(vstore_pending_names[i], NAME_LEN, "vstore_pending_%d", i);
1403 hex_vstore_pending[i] = tcg_global_mem_new(tcg_env,
1404 offsetof(CPUHexagonState, vstore_pending[i]),
1405 vstore_pending_names[i]);
1406 }
1407 }