target/hexagon: Add pkt_ends_tb to translation
Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
Brian Cain committed
Jun 22, 2026 at 15:28 UTC
5312546b4fd0c2dbca7dd7b4a2a4e865de2e418d
2 files changed
+100
-3
target/hexagon/translate.c
+100
-2
@@ -270,6 +270,16 @@ static bool check_for_attrib(Packet *pkt, int attrib)
270
return false;
271
}
272
273
+static bool check_for_opcode(Packet *pkt, uint16_t opcode)
274
+{
275
+ for (int i = 0; i < pkt->num_insns; i++) {
276
+ if (pkt->insn[i].opcode == opcode) {
277
+ return true;
278
+ }
279
+ }
280
+ return false;
281
+}
282
+
283
static bool need_slot_cancelled(Packet *pkt)
284
{
285
/* We only need slot_cancelled for conditional store instructions */
@@ -283,6 +293,90 @@ static bool need_slot_cancelled(Packet *pkt)
293
return false;
294
}
295
296
+#ifndef CONFIG_USER_ONLY
297
+static bool sreg_write_ends_tb(int reg_num)
298
+{
299
+ return reg_num == HEX_SREG_SSR ||
300
+ reg_num == HEX_SREG_STID ||
301
+ reg_num == HEX_SREG_IMASK ||
302
+ reg_num == HEX_SREG_IPENDAD ||
303
+ reg_num == HEX_SREG_BESTWAIT ||
304
+ reg_num == HEX_SREG_SCHEDCFG;
305
+}
306
+
307
+static bool has_sreg_write_ends_tb(Packet const *pkt)
308
+{
309
+ for (int i = 0; i < pkt->num_insns; i++) {
310
+ Insn const *insn = &pkt->insn[i];
311
+ uint16_t opcode = insn->opcode;
312
+ if (opcode == Y2_tfrsrcr) {
313
+ /* Write to a single sreg */
314
+ int reg_num = insn->regno[0];
315
+ if (sreg_write_ends_tb(reg_num)) {
316
+ return true;
317
+ }
318
+ } else if (opcode == Y4_tfrspcp) {
319
+ /* Write to a sreg pair */
320
+ int reg_num = insn->regno[0];
321
+ if (sreg_write_ends_tb(reg_num)) {
322
+ return true;
323
+ }
324
+ if (sreg_write_ends_tb(reg_num + 1)) {
325
+ return true;
326
+ }
327
+ }
328
+ }
329
+ return false;
330
+}
331
+#endif
332
+
333
+static bool pkt_ends_tb(Packet *pkt)
334
+{
335
+ if (pkt->pkt_has_cof) {
336
+ return true;
337
+ }
338
+#ifndef CONFIG_USER_ONLY
339
+ /* System mode instructions that end TLB */
340
+ if (check_for_opcode(pkt, Y2_swi) ||
341
+ check_for_opcode(pkt, Y2_cswi) ||
342
+ check_for_opcode(pkt, Y2_ciad) ||
343
+ check_for_opcode(pkt, Y4_siad) ||
344
+ check_for_opcode(pkt, Y2_wait) ||
345
+ check_for_opcode(pkt, Y2_resume) ||
346
+ check_for_opcode(pkt, Y2_iassignw) ||
347
+ check_for_opcode(pkt, Y2_setimask) ||
348
+ check_for_opcode(pkt, Y4_nmi) ||
349
+ check_for_opcode(pkt, Y2_setprio) ||
350
+ check_for_opcode(pkt, Y2_start) ||
351
+ check_for_opcode(pkt, Y2_stop) ||
352
+ check_for_opcode(pkt, Y2_k0lock) ||
353
+ check_for_opcode(pkt, Y2_k0unlock) ||
354
+ check_for_opcode(pkt, Y2_tlblock) ||
355
+ check_for_opcode(pkt, Y2_tlbunlock) ||
356
+ check_for_opcode(pkt, Y2_break) ||
357
+ check_for_opcode(pkt, Y2_isync) ||
358
+ check_for_opcode(pkt, Y2_syncht) ||
359
+ check_for_opcode(pkt, Y2_tlbp) ||
360
+ check_for_opcode(pkt, Y2_tlbw) ||
361
+ check_for_opcode(pkt, Y5_ctlbw) ||
362
+ check_for_opcode(pkt, Y5_tlbasidi)) {
363
+ return true;
364
+ }
365
+
366
+ /*
367
+ * Check for sreg writes that would end the TB
368
+ */
369
+ if (check_for_attrib(pkt, A_IMPLICIT_WRITES_SSR)) {
370
+ return true;
371
+ }
372
+ if (has_sreg_write_ends_tb(pkt)) {
373
+ return true;
374
+ }
375
+#endif
376
+ return false;
377
+}
378
+
379
+
380
static bool need_next_PC(DisasContext *ctx)
381
{
382
/* Check for conditional control flow or HW loop end */
@@ -439,7 +533,11 @@ static void analyze_packet(DisasContext *ctx)
533
534
static void gen_start_packet(DisasContext *ctx)
535
{
442
- target_ulong next_PC = ctx->base.pc_next + ctx->pkt.encod_pkt_size_in_bytes;
536
+ Packet *pkt = &ctx->pkt;
537
+ target_ulong next_PC = (check_for_opcode(pkt, Y2_k0lock) ||
538
+ check_for_opcode(pkt, Y2_tlblock)) ?
539
+ ctx->base.pc_next :
540
+ ctx->base.pc_next + pkt->encod_pkt_size_in_bytes;
541
int i;
542
543
/* Clear out the disassembly context */
@@ -944,7 +1042,7 @@ static void gen_commit_packet(DisasContext *ctx)
1042
ctx->pkt.vhist_insn->generate(ctx);
1043
}
1044
947
- if (ctx->pkt.pkt_has_cof) {
1045
+ if (pkt_ends_tb(&ctx->pkt) || ctx->base.is_jmp == DISAS_NORETURN) {
1046
gen_end_tb(ctx);
1047
}
1048
}
target/hexagon/translate.h
-1
@@ -86,7 +86,6 @@ typedef struct DisasContext {
86
TCGv branch_taken;
87
TCGv dczero_addr;
88
bool pcycle_enabled;
89
- bool pkt_ends_tb;
89
uint32_t num_cycles;
90
} DisasContext;
91