Commit 89d61955e7 for qemu.org
commit 89d61955e73bce56acea7982236037bf206d5f6b
Author: Matheus Tavares Bernardino <matheus.bernardino@oss.qualcomm.com>
Date: Mon Aug 24 08:58:13 2026 -0700
target/hexagon: fix PC advancement for non-COF TB terminators
Some packets end a translation block without a change-of-flow. These do
not update the PC during commit, so gen_end_tb() leaves
hex_gpr[HEX_REG_PC] pointing at the same packet and the block gets
re-entered forever. Set PC explicitly to next_PC in that gen_end_tb()
branch to fix execution of next blocks.
Note that gen_start_packet() used to have a special case for
tlblock/k0lock, setting ctx->next_PC to the packet's own address. This
relies on the tlblock/k0lock helpers to properly advance the PC, which
is never done (only env->next_PC is updated, but that never reaches
hex_gpr[HEX_REG_PC]). Drop the special case so these packets advance to
the following packet like any other non-COF TB terminator.
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
Signed-off-by: Matheus Tavares Bernardino <matheus.bernardino@oss.qualcomm.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 06a8159d28..5463a07ec5 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -217,6 +217,12 @@ static void gen_end_tb(DisasContext *ctx)
gen_goto_tb(ctx, 0, ctx->base.tb->pc, true);
gen_set_label(skip);
gen_goto_tb(ctx, 1, ctx->next_PC, false);
+ } else if (!ctx->pkt.pkt_has_cof) {
+ /*
+ * Packet with no deferred COF that still ends the TB. PC is
+ * not updated during commit, so set it explicitly to next_PC.
+ */
+ gen_goto_tb(ctx, 0, ctx->next_PC, true);
} else {
tcg_gen_lookup_and_goto_ptr();
}
@@ -289,6 +295,7 @@ static bool check_for_attrib(Packet *pkt, int attrib)
return false;
}
+#ifndef CONFIG_USER_ONLY
static bool check_for_opcode(Packet *pkt, uint16_t opcode)
{
for (int i = 0; i < pkt->num_insns; i++) {
@@ -298,6 +305,7 @@ static bool check_for_opcode(Packet *pkt, uint16_t opcode)
}
return false;
}
+#endif
static bool need_slot_cancelled(Packet *pkt)
{
@@ -577,10 +585,7 @@ static void analyze_packet(DisasContext *ctx)
static void gen_start_packet(DisasContext *ctx)
{
Packet *pkt = &ctx->pkt;
- target_ulong next_PC = (check_for_opcode(pkt, Y2_k0lock) ||
- check_for_opcode(pkt, Y2_tlblock)) ?
- ctx->base.pc_next :
- ctx->base.pc_next + pkt->encod_pkt_size_in_bytes;
+ target_ulong next_PC = ctx->base.pc_next + pkt->encod_pkt_size_in_bytes;
int i;
/* Clear out the disassembly context */