On Wed, Oct 14, 2026 at 2:52 PM Brian Cain <[email protected]> wrote:
>
> gen_callr wrote the link register before consuming the target, so
> "callr r31" jumped to the new return address instead of the old LR
> value.  Copy the target to a temporary first.
>
> Signed-off-by: Brian Cain <[email protected]>
> ---
>  target/hexagon/genptr.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
> index f264bb9d0a0..7ef60244de0 100644
> --- a/target/hexagon/genptr.c
> +++ b/target/hexagon/genptr.c
> @@ -1028,9 +1028,13 @@ static void gen_call(DisasContext *ctx, int pc_off)
>
>  static void gen_callr(DisasContext *ctx, TCGv new_pc)
>  {
> +    TCGv target = tcg_temp_new();
>      TCGv lr = get_result_gpr(ctx, HEX_REG_LR);
> +
> +    /* Preserve the target when callr uses LR as its source register. */
> +    tcg_gen_mov_tl(target, new_pc);
>      tcg_gen_movi_tl(lr, ctx->next_PC);
> -    gen_write_new_pc_addr(ctx, new_pc, TCG_COND_ALWAYS, NULL);
> +    gen_write_new_pc_addr(ctx, target, TCG_COND_ALWAYS, NULL);
>  }

This could make use of `gen_unalias_gpr_src`.

Reply via email to