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 <[email protected]> Signed-off-by: Matheus Tavares Bernardino <[email protected]> --- target/hexagon/translate.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c index 341842c6af1..f8b87c279e5 100644 --- a/target/hexagon/translate.c +++ b/target/hexagon/translate.c @@ -210,6 +210,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(); } @@ -286,6 +292,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++) { @@ -295,6 +302,7 @@ static bool check_for_opcode(Packet *pkt, uint16_t opcode) } return false; } +#endif static bool need_slot_cancelled(Packet *pkt) { @@ -566,10 +574,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 */ -- 2.37.2
