diff mbox series

[v6,3/6] target/riscv: Fix target address to update badaddr

Message ID 20230404020653.18911-4-liweiwei@iscas.ac.cn (mailing list archive)
State New, archived
Headers show
Series target/riscv: Fix pointer mask related support | expand

Commit Message

Weiwei Li April 4, 2023, 2:06 a.m. UTC
Compute the target address before storing it into badaddr
when mis-aligned exception is triggered.
Use a target_pc temp to store the target address to avoid
the confusing operation that udpate target address into
cpu_pc before misalign check, then update it into badaddr
and restore cpu_pc to current pc if exception is triggered.

Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn>
Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/insn_trans/trans_rvi.c.inc | 23 ++++++++++++++++-------
 target/riscv/translate.c                | 21 ++++++++++-----------
 2 files changed, 26 insertions(+), 18 deletions(-)

Comments

LIU Zhiwei April 4, 2023, 3:06 a.m. UTC | #1
On 2023/4/4 10:06, Weiwei Li wrote:
> Compute the target address before storing it into badaddr
> when mis-aligned exception is triggered.
> Use a target_pc temp to store the target address to avoid
> the confusing operation that udpate target address into
> cpu_pc before misalign check, then update it into badaddr
> and restore cpu_pc to current pc if exception is triggered.
>
> Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn>
> Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   target/riscv/insn_trans/trans_rvi.c.inc | 23 ++++++++++++++++-------
>   target/riscv/translate.c                | 21 ++++++++++-----------
>   2 files changed, 26 insertions(+), 18 deletions(-)
>
> diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc
> index 4ad54e8a49..cc72864d32 100644
> --- a/target/riscv/insn_trans/trans_rvi.c.inc
> +++ b/target/riscv/insn_trans/trans_rvi.c.inc
> @@ -51,25 +51,30 @@ static bool trans_jal(DisasContext *ctx, arg_jal *a)
>   static bool trans_jalr(DisasContext *ctx, arg_jalr *a)
>   {
>       TCGLabel *misaligned = NULL;
> +    TCGv target_pc = tcg_temp_new();
>   
> -    tcg_gen_addi_tl(cpu_pc, get_gpr(ctx, a->rs1, EXT_NONE), a->imm);
> -    tcg_gen_andi_tl(cpu_pc, cpu_pc, (target_ulong)-2);
> +    tcg_gen_addi_tl(target_pc, get_gpr(ctx, a->rs1, EXT_NONE), a->imm);
> +    tcg_gen_andi_tl(target_pc, target_pc, (target_ulong)-2);
> +
> +    if (get_xl(ctx) == MXL_RV32) {
> +        tcg_gen_ext32s_tl(target_pc, target_pc);
> +    }
>   
Delete this.
> -    gen_set_pc(ctx, cpu_pc);
>       if (!has_ext(ctx, RVC)) {
>           TCGv t0 = tcg_temp_new();
>   
>           misaligned = gen_new_label();
> -        tcg_gen_andi_tl(t0, cpu_pc, 0x2);
> +        tcg_gen_andi_tl(t0, target_pc, 0x2);
>           tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x0, misaligned);
>       }
>   
>       gen_set_gpri(ctx, a->rd, ctx->pc_succ_insn);
> +    tcg_gen_mov_tl(cpu_pc, target_pc);

And we can use the gen_set_pc instead.

I think the reason you want to delete gen_set_pc is to make the 
gen_set_pc_imm the only API to change the cpu_pc.

This implicitly enhance the correctness, which may constrain the scalable.

Zhiwei

>       lookup_and_goto_ptr(ctx);
>   
>       if (misaligned) {
>           gen_set_label(misaligned);
> -        gen_exception_inst_addr_mis(ctx);
> +        gen_exception_inst_addr_mis(ctx, target_pc);
>       }
>       ctx->base.is_jmp = DISAS_NORETURN;
>   
> @@ -153,6 +158,7 @@ static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond cond)
>       TCGLabel *l = gen_new_label();
>       TCGv src1 = get_gpr(ctx, a->rs1, EXT_SIGN);
>       TCGv src2 = get_gpr(ctx, a->rs2, EXT_SIGN);
> +    target_ulong next_pc;
>   
>       if (get_xl(ctx) == MXL_RV128) {
>           TCGv src1h = get_gprh(ctx, a->rs1);
> @@ -169,9 +175,12 @@ static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond cond)
>   
>       gen_set_label(l); /* branch taken */
>   
> -    if (!has_ext(ctx, RVC) && ((ctx->base.pc_next + a->imm) & 0x3)) {
> +    next_pc = ctx->base.pc_next + a->imm;
> +    if (!has_ext(ctx, RVC) && (next_pc & 0x3)) {
>           /* misaligned */
> -        gen_exception_inst_addr_mis(ctx);
> +        TCGv target_pc = tcg_temp_new();
> +        gen_pc_plus_diff(target_pc, ctx, next_pc);
> +        gen_exception_inst_addr_mis(ctx, target_pc);
>       } else {
>           gen_goto_tb(ctx, 0, ctx->base.pc_next + a->imm);
>       }
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index 0ee8ee147d..d434fedb37 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -222,21 +222,18 @@ static void decode_save_opc(DisasContext *ctx)
>       ctx->insn_start = NULL;
>   }
>   
> -static void gen_set_pc_imm(DisasContext *ctx, target_ulong dest)
> +static void gen_pc_plus_diff(TCGv target, DisasContext *ctx,
> +                              target_ulong dest)
>   {
>       if (get_xl(ctx) == MXL_RV32) {
>           dest = (int32_t)dest;
>       }
> -    tcg_gen_movi_tl(cpu_pc, dest);
> +    tcg_gen_movi_tl(target, dest);
>   }
>   
> -static void gen_set_pc(DisasContext *ctx, TCGv dest)
> +static void gen_set_pc_imm(DisasContext *ctx, target_ulong dest)
>   {
> -    if (get_xl(ctx) == MXL_RV32) {
> -        tcg_gen_ext32s_tl(cpu_pc, dest);
> -    } else {
> -        tcg_gen_mov_tl(cpu_pc, dest);
> -    }
> +    gen_pc_plus_diff(cpu_pc, ctx, dest);
>   }
>   
>   static void generate_exception(DisasContext *ctx, int excp)
> @@ -257,9 +254,9 @@ static void gen_exception_illegal(DisasContext *ctx)
>       }
>   }
>   
> -static void gen_exception_inst_addr_mis(DisasContext *ctx)
> +static void gen_exception_inst_addr_mis(DisasContext *ctx, TCGv target)
>   {
> -    tcg_gen_st_tl(cpu_pc, cpu_env, offsetof(CPURISCVState, badaddr));
> +    tcg_gen_st_tl(target, cpu_env, offsetof(CPURISCVState, badaddr));
>       generate_exception(ctx, RISCV_EXCP_INST_ADDR_MIS);
>   }
>   
> @@ -551,7 +548,9 @@ static void gen_jal(DisasContext *ctx, int rd, target_ulong imm)
>       next_pc = ctx->base.pc_next + imm;
>       if (!has_ext(ctx, RVC)) {
>           if ((next_pc & 0x3) != 0) {
> -            gen_exception_inst_addr_mis(ctx);
> +            TCGv target_pc = tcg_temp_new();
> +            gen_pc_plus_diff(target_pc, ctx, next_pc);
> +            gen_exception_inst_addr_mis(ctx, target_pc);
>               return;
>           }
>       }
Weiwei Li April 4, 2023, 3:37 a.m. UTC | #2
On 2023/4/4 11:06, LIU Zhiwei wrote:
>
> On 2023/4/4 10:06, Weiwei Li wrote:
>> Compute the target address before storing it into badaddr
>> when mis-aligned exception is triggered.
>> Use a target_pc temp to store the target address to avoid
>> the confusing operation that udpate target address into
>> cpu_pc before misalign check, then update it into badaddr
>> and restore cpu_pc to current pc if exception is triggered.
>>
>> Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn>
>> Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn>
>> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>>   target/riscv/insn_trans/trans_rvi.c.inc | 23 ++++++++++++++++-------
>>   target/riscv/translate.c                | 21 ++++++++++-----------
>>   2 files changed, 26 insertions(+), 18 deletions(-)
>>
>> diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
>> b/target/riscv/insn_trans/trans_rvi.c.inc
>> index 4ad54e8a49..cc72864d32 100644
>> --- a/target/riscv/insn_trans/trans_rvi.c.inc
>> +++ b/target/riscv/insn_trans/trans_rvi.c.inc
>> @@ -51,25 +51,30 @@ static bool trans_jal(DisasContext *ctx, arg_jal *a)
>>   static bool trans_jalr(DisasContext *ctx, arg_jalr *a)
>>   {
>>       TCGLabel *misaligned = NULL;
>> +    TCGv target_pc = tcg_temp_new();
>>   -    tcg_gen_addi_tl(cpu_pc, get_gpr(ctx, a->rs1, EXT_NONE), a->imm);
>> -    tcg_gen_andi_tl(cpu_pc, cpu_pc, (target_ulong)-2);
>> +    tcg_gen_addi_tl(target_pc, get_gpr(ctx, a->rs1, EXT_NONE), a->imm);
>> +    tcg_gen_andi_tl(target_pc, target_pc, (target_ulong)-2);
>> +
>> +    if (get_xl(ctx) == MXL_RV32) {
>> +        tcg_gen_ext32s_tl(target_pc, target_pc);
>> +    }
> Delete this.

The (signed-extended)target_pc should be used in both updating cpu_pc 
and  following gen_exception_inst_addr_mis().

So we cannot delete it and just resue  the logic in gen_set_pc().

This is also why  I use  tcg_gen_mov_tl(cpu_pc, target_pc) directly in 
following code.

Regards,

Weiwei Li

>> -    gen_set_pc(ctx, cpu_pc);
>>       if (!has_ext(ctx, RVC)) {
>>           TCGv t0 = tcg_temp_new();
>>             misaligned = gen_new_label();
>> -        tcg_gen_andi_tl(t0, cpu_pc, 0x2);
>> +        tcg_gen_andi_tl(t0, target_pc, 0x2);
>>           tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x0, misaligned);
>>       }
>>         gen_set_gpri(ctx, a->rd, ctx->pc_succ_insn);
>> +    tcg_gen_mov_tl(cpu_pc, target_pc);
>
> And we can use the gen_set_pc instead.
>
> I think the reason you want to delete gen_set_pc is to make the 
> gen_set_pc_imm the only API to change the cpu_pc.
>
> This implicitly enhance the correctness, which may constrain the 
> scalable.
>
> Zhiwei
>
>>       lookup_and_goto_ptr(ctx);
>>         if (misaligned) {
>>           gen_set_label(misaligned);
>> -        gen_exception_inst_addr_mis(ctx);
>> +        gen_exception_inst_addr_mis(ctx, target_pc);
>>       }
>>       ctx->base.is_jmp = DISAS_NORETURN;
>>   @@ -153,6 +158,7 @@ static bool gen_branch(DisasContext *ctx, arg_b 
>> *a, TCGCond cond)
>>       TCGLabel *l = gen_new_label();
>>       TCGv src1 = get_gpr(ctx, a->rs1, EXT_SIGN);
>>       TCGv src2 = get_gpr(ctx, a->rs2, EXT_SIGN);
>> +    target_ulong next_pc;
>>         if (get_xl(ctx) == MXL_RV128) {
>>           TCGv src1h = get_gprh(ctx, a->rs1);
>> @@ -169,9 +175,12 @@ static bool gen_branch(DisasContext *ctx, arg_b 
>> *a, TCGCond cond)
>>         gen_set_label(l); /* branch taken */
>>   -    if (!has_ext(ctx, RVC) && ((ctx->base.pc_next + a->imm) & 0x3)) {
>> +    next_pc = ctx->base.pc_next + a->imm;
>> +    if (!has_ext(ctx, RVC) && (next_pc & 0x3)) {
>>           /* misaligned */
>> -        gen_exception_inst_addr_mis(ctx);
>> +        TCGv target_pc = tcg_temp_new();
>> +        gen_pc_plus_diff(target_pc, ctx, next_pc);
>> +        gen_exception_inst_addr_mis(ctx, target_pc);
>>       } else {
>>           gen_goto_tb(ctx, 0, ctx->base.pc_next + a->imm);
>>       }
>> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
>> index 0ee8ee147d..d434fedb37 100644
>> --- a/target/riscv/translate.c
>> +++ b/target/riscv/translate.c
>> @@ -222,21 +222,18 @@ static void decode_save_opc(DisasContext *ctx)
>>       ctx->insn_start = NULL;
>>   }
>>   -static void gen_set_pc_imm(DisasContext *ctx, target_ulong dest)
>> +static void gen_pc_plus_diff(TCGv target, DisasContext *ctx,
>> +                              target_ulong dest)
>>   {
>>       if (get_xl(ctx) == MXL_RV32) {
>>           dest = (int32_t)dest;
>>       }
>> -    tcg_gen_movi_tl(cpu_pc, dest);
>> +    tcg_gen_movi_tl(target, dest);
>>   }
>>   -static void gen_set_pc(DisasContext *ctx, TCGv dest)
>> +static void gen_set_pc_imm(DisasContext *ctx, target_ulong dest)
>>   {
>> -    if (get_xl(ctx) == MXL_RV32) {
>> -        tcg_gen_ext32s_tl(cpu_pc, dest);
>> -    } else {
>> -        tcg_gen_mov_tl(cpu_pc, dest);
>> -    }
>> +    gen_pc_plus_diff(cpu_pc, ctx, dest);
>>   }
>>     static void generate_exception(DisasContext *ctx, int excp)
>> @@ -257,9 +254,9 @@ static void gen_exception_illegal(DisasContext *ctx)
>>       }
>>   }
>>   -static void gen_exception_inst_addr_mis(DisasContext *ctx)
>> +static void gen_exception_inst_addr_mis(DisasContext *ctx, TCGv target)
>>   {
>> -    tcg_gen_st_tl(cpu_pc, cpu_env, offsetof(CPURISCVState, badaddr));
>> +    tcg_gen_st_tl(target, cpu_env, offsetof(CPURISCVState, badaddr));
>>       generate_exception(ctx, RISCV_EXCP_INST_ADDR_MIS);
>>   }
>>   @@ -551,7 +548,9 @@ static void gen_jal(DisasContext *ctx, int rd, 
>> target_ulong imm)
>>       next_pc = ctx->base.pc_next + imm;
>>       if (!has_ext(ctx, RVC)) {
>>           if ((next_pc & 0x3) != 0) {
>> -            gen_exception_inst_addr_mis(ctx);
>> +            TCGv target_pc = tcg_temp_new();
>> +            gen_pc_plus_diff(target_pc, ctx, next_pc);
>> +            gen_exception_inst_addr_mis(ctx, target_pc);
>>               return;
>>           }
>>       }
Alistair Francis April 5, 2023, 4:41 a.m. UTC | #3
On Tue, Apr 4, 2023 at 12:08 PM Weiwei Li <liweiwei@iscas.ac.cn> wrote:
>
> Compute the target address before storing it into badaddr
> when mis-aligned exception is triggered.
> Use a target_pc temp to store the target address to avoid
> the confusing operation that udpate target address into
> cpu_pc before misalign check, then update it into badaddr
> and restore cpu_pc to current pc if exception is triggered.
>
> Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn>
> Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/insn_trans/trans_rvi.c.inc | 23 ++++++++++++++++-------
>  target/riscv/translate.c                | 21 ++++++++++-----------
>  2 files changed, 26 insertions(+), 18 deletions(-)
>
> diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc
> index 4ad54e8a49..cc72864d32 100644
> --- a/target/riscv/insn_trans/trans_rvi.c.inc
> +++ b/target/riscv/insn_trans/trans_rvi.c.inc
> @@ -51,25 +51,30 @@ static bool trans_jal(DisasContext *ctx, arg_jal *a)
>  static bool trans_jalr(DisasContext *ctx, arg_jalr *a)
>  {
>      TCGLabel *misaligned = NULL;
> +    TCGv target_pc = tcg_temp_new();
>
> -    tcg_gen_addi_tl(cpu_pc, get_gpr(ctx, a->rs1, EXT_NONE), a->imm);
> -    tcg_gen_andi_tl(cpu_pc, cpu_pc, (target_ulong)-2);
> +    tcg_gen_addi_tl(target_pc, get_gpr(ctx, a->rs1, EXT_NONE), a->imm);
> +    tcg_gen_andi_tl(target_pc, target_pc, (target_ulong)-2);
> +
> +    if (get_xl(ctx) == MXL_RV32) {
> +        tcg_gen_ext32s_tl(target_pc, target_pc);
> +    }
>
> -    gen_set_pc(ctx, cpu_pc);
>      if (!has_ext(ctx, RVC)) {
>          TCGv t0 = tcg_temp_new();
>
>          misaligned = gen_new_label();
> -        tcg_gen_andi_tl(t0, cpu_pc, 0x2);
> +        tcg_gen_andi_tl(t0, target_pc, 0x2);
>          tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x0, misaligned);
>      }
>
>      gen_set_gpri(ctx, a->rd, ctx->pc_succ_insn);
> +    tcg_gen_mov_tl(cpu_pc, target_pc);
>      lookup_and_goto_ptr(ctx);
>
>      if (misaligned) {
>          gen_set_label(misaligned);
> -        gen_exception_inst_addr_mis(ctx);
> +        gen_exception_inst_addr_mis(ctx, target_pc);
>      }
>      ctx->base.is_jmp = DISAS_NORETURN;
>
> @@ -153,6 +158,7 @@ static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond cond)
>      TCGLabel *l = gen_new_label();
>      TCGv src1 = get_gpr(ctx, a->rs1, EXT_SIGN);
>      TCGv src2 = get_gpr(ctx, a->rs2, EXT_SIGN);
> +    target_ulong next_pc;
>
>      if (get_xl(ctx) == MXL_RV128) {
>          TCGv src1h = get_gprh(ctx, a->rs1);
> @@ -169,9 +175,12 @@ static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond cond)
>
>      gen_set_label(l); /* branch taken */
>
> -    if (!has_ext(ctx, RVC) && ((ctx->base.pc_next + a->imm) & 0x3)) {
> +    next_pc = ctx->base.pc_next + a->imm;
> +    if (!has_ext(ctx, RVC) && (next_pc & 0x3)) {
>          /* misaligned */
> -        gen_exception_inst_addr_mis(ctx);
> +        TCGv target_pc = tcg_temp_new();
> +        gen_pc_plus_diff(target_pc, ctx, next_pc);
> +        gen_exception_inst_addr_mis(ctx, target_pc);
>      } else {
>          gen_goto_tb(ctx, 0, ctx->base.pc_next + a->imm);
>      }
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index 0ee8ee147d..d434fedb37 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -222,21 +222,18 @@ static void decode_save_opc(DisasContext *ctx)
>      ctx->insn_start = NULL;
>  }
>
> -static void gen_set_pc_imm(DisasContext *ctx, target_ulong dest)
> +static void gen_pc_plus_diff(TCGv target, DisasContext *ctx,
> +                              target_ulong dest)
>  {
>      if (get_xl(ctx) == MXL_RV32) {
>          dest = (int32_t)dest;
>      }
> -    tcg_gen_movi_tl(cpu_pc, dest);
> +    tcg_gen_movi_tl(target, dest);
>  }
>
> -static void gen_set_pc(DisasContext *ctx, TCGv dest)
> +static void gen_set_pc_imm(DisasContext *ctx, target_ulong dest)
>  {
> -    if (get_xl(ctx) == MXL_RV32) {
> -        tcg_gen_ext32s_tl(cpu_pc, dest);
> -    } else {
> -        tcg_gen_mov_tl(cpu_pc, dest);
> -    }
> +    gen_pc_plus_diff(cpu_pc, ctx, dest);
>  }
>
>  static void generate_exception(DisasContext *ctx, int excp)
> @@ -257,9 +254,9 @@ static void gen_exception_illegal(DisasContext *ctx)
>      }
>  }
>
> -static void gen_exception_inst_addr_mis(DisasContext *ctx)
> +static void gen_exception_inst_addr_mis(DisasContext *ctx, TCGv target)
>  {
> -    tcg_gen_st_tl(cpu_pc, cpu_env, offsetof(CPURISCVState, badaddr));
> +    tcg_gen_st_tl(target, cpu_env, offsetof(CPURISCVState, badaddr));
>      generate_exception(ctx, RISCV_EXCP_INST_ADDR_MIS);
>  }
>
> @@ -551,7 +548,9 @@ static void gen_jal(DisasContext *ctx, int rd, target_ulong imm)
>      next_pc = ctx->base.pc_next + imm;
>      if (!has_ext(ctx, RVC)) {
>          if ((next_pc & 0x3) != 0) {
> -            gen_exception_inst_addr_mis(ctx);
> +            TCGv target_pc = tcg_temp_new();
> +            gen_pc_plus_diff(target_pc, ctx, next_pc);
> +            gen_exception_inst_addr_mis(ctx, target_pc);
>              return;
>          }
>      }
> --
> 2.25.1
>
>
diff mbox series

Patch

diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc
index 4ad54e8a49..cc72864d32 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -51,25 +51,30 @@  static bool trans_jal(DisasContext *ctx, arg_jal *a)
 static bool trans_jalr(DisasContext *ctx, arg_jalr *a)
 {
     TCGLabel *misaligned = NULL;
+    TCGv target_pc = tcg_temp_new();
 
-    tcg_gen_addi_tl(cpu_pc, get_gpr(ctx, a->rs1, EXT_NONE), a->imm);
-    tcg_gen_andi_tl(cpu_pc, cpu_pc, (target_ulong)-2);
+    tcg_gen_addi_tl(target_pc, get_gpr(ctx, a->rs1, EXT_NONE), a->imm);
+    tcg_gen_andi_tl(target_pc, target_pc, (target_ulong)-2);
+
+    if (get_xl(ctx) == MXL_RV32) {
+        tcg_gen_ext32s_tl(target_pc, target_pc);
+    }
 
-    gen_set_pc(ctx, cpu_pc);
     if (!has_ext(ctx, RVC)) {
         TCGv t0 = tcg_temp_new();
 
         misaligned = gen_new_label();
-        tcg_gen_andi_tl(t0, cpu_pc, 0x2);
+        tcg_gen_andi_tl(t0, target_pc, 0x2);
         tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x0, misaligned);
     }
 
     gen_set_gpri(ctx, a->rd, ctx->pc_succ_insn);
+    tcg_gen_mov_tl(cpu_pc, target_pc);
     lookup_and_goto_ptr(ctx);
 
     if (misaligned) {
         gen_set_label(misaligned);
-        gen_exception_inst_addr_mis(ctx);
+        gen_exception_inst_addr_mis(ctx, target_pc);
     }
     ctx->base.is_jmp = DISAS_NORETURN;
 
@@ -153,6 +158,7 @@  static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond cond)
     TCGLabel *l = gen_new_label();
     TCGv src1 = get_gpr(ctx, a->rs1, EXT_SIGN);
     TCGv src2 = get_gpr(ctx, a->rs2, EXT_SIGN);
+    target_ulong next_pc;
 
     if (get_xl(ctx) == MXL_RV128) {
         TCGv src1h = get_gprh(ctx, a->rs1);
@@ -169,9 +175,12 @@  static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond cond)
 
     gen_set_label(l); /* branch taken */
 
-    if (!has_ext(ctx, RVC) && ((ctx->base.pc_next + a->imm) & 0x3)) {
+    next_pc = ctx->base.pc_next + a->imm;
+    if (!has_ext(ctx, RVC) && (next_pc & 0x3)) {
         /* misaligned */
-        gen_exception_inst_addr_mis(ctx);
+        TCGv target_pc = tcg_temp_new();
+        gen_pc_plus_diff(target_pc, ctx, next_pc);
+        gen_exception_inst_addr_mis(ctx, target_pc);
     } else {
         gen_goto_tb(ctx, 0, ctx->base.pc_next + a->imm);
     }
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 0ee8ee147d..d434fedb37 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -222,21 +222,18 @@  static void decode_save_opc(DisasContext *ctx)
     ctx->insn_start = NULL;
 }
 
-static void gen_set_pc_imm(DisasContext *ctx, target_ulong dest)
+static void gen_pc_plus_diff(TCGv target, DisasContext *ctx,
+                              target_ulong dest)
 {
     if (get_xl(ctx) == MXL_RV32) {
         dest = (int32_t)dest;
     }
-    tcg_gen_movi_tl(cpu_pc, dest);
+    tcg_gen_movi_tl(target, dest);
 }
 
-static void gen_set_pc(DisasContext *ctx, TCGv dest)
+static void gen_set_pc_imm(DisasContext *ctx, target_ulong dest)
 {
-    if (get_xl(ctx) == MXL_RV32) {
-        tcg_gen_ext32s_tl(cpu_pc, dest);
-    } else {
-        tcg_gen_mov_tl(cpu_pc, dest);
-    }
+    gen_pc_plus_diff(cpu_pc, ctx, dest);
 }
 
 static void generate_exception(DisasContext *ctx, int excp)
@@ -257,9 +254,9 @@  static void gen_exception_illegal(DisasContext *ctx)
     }
 }
 
-static void gen_exception_inst_addr_mis(DisasContext *ctx)
+static void gen_exception_inst_addr_mis(DisasContext *ctx, TCGv target)
 {
-    tcg_gen_st_tl(cpu_pc, cpu_env, offsetof(CPURISCVState, badaddr));
+    tcg_gen_st_tl(target, cpu_env, offsetof(CPURISCVState, badaddr));
     generate_exception(ctx, RISCV_EXCP_INST_ADDR_MIS);
 }
 
@@ -551,7 +548,9 @@  static void gen_jal(DisasContext *ctx, int rd, target_ulong imm)
     next_pc = ctx->base.pc_next + imm;
     if (!has_ext(ctx, RVC)) {
         if ((next_pc & 0x3) != 0) {
-            gen_exception_inst_addr_mis(ctx);
+            TCGv target_pc = tcg_temp_new();
+            gen_pc_plus_diff(target_pc, ctx, next_pc);
+            gen_exception_inst_addr_mis(ctx, target_pc);
             return;
         }
     }