target/arm: Fix temp double-free in sve ldr/str

The temp that gets assigned to clean_addr has been allocated with
new_tmp_a64, which means that it will be freed at the end of the
instruction. Freeing it earlier leads to assertion failure.

The loop creates a complication, in which we allocate a new local
temp, which does need freeing, and the final code path is shared
between the loop and non-loop.

Fix this complication by adding new_tmp_a64_local so that the new
local temp is freed at the end, and can be treated exactly like
the non-loop path.

Fixes: bba87d0a0f4

Backports commit 4b4dc9750a0aa0b9766bd755bf6512a84744ce8a from qemu
This commit is contained in:
Richard Henderson 2021-02-25 23:06:03 -05:00 committed by Lioncash
parent 54e2107bdf
commit 57c66389c2
6 changed files with 14 additions and 6 deletions

View file

@ -4858,6 +4858,7 @@
#define mte_checkN_ mte_checkN__aarch64
#define mte_probe1 mte_probe1_aarch64
#define new_tmp_a64 new_tmp_a64_aarch64
#define new_tmp_a64_local new_tmp_a64_local_aarch64
#define new_tmp_a64_zero new_tmp_a64_zero_aarch64
#define pmsav8_mpu_lookup pmsav8_mpu_lookup_aarch64
#define pmu_op_start pmu_op_start_aarch64

View file

@ -4858,6 +4858,7 @@
#define mte_checkN_ mte_checkN__aarch64eb
#define mte_probe1 mte_probe1_aarch64eb
#define new_tmp_a64 new_tmp_a64_aarch64eb
#define new_tmp_a64_local new_tmp_a64_local_aarch64eb
#define new_tmp_a64_zero new_tmp_a64_zero_aarch64eb
#define pmsav8_mpu_lookup pmsav8_mpu_lookup_aarch64eb
#define pmu_op_start pmu_op_start_aarch64eb

View file

@ -4998,6 +4998,7 @@ aarch64_symbols = (
'mte_checkN_',
'mte_probe1',
'new_tmp_a64',
'new_tmp_a64_local',
'new_tmp_a64_zero',
'pmsav8_mpu_lookup',
'pmu_op_start',

View file

@ -607,6 +607,14 @@ TCGv_i64 new_tmp_a64(DisasContext *s)
return s->tmp_a64[s->tmp_a64_count++] = tcg_temp_new_i64(tcg_ctx);
}
TCGv_i64 new_tmp_a64_local(DisasContext *s)
{
TCGContext *tcg_ctx = s->uc->tcg_ctx;
assert(s->tmp_a64_count < TMP_A64_MAX);
return s->tmp_a64[s->tmp_a64_count++] = tcg_temp_local_new_i64(tcg_ctx);
}
TCGv_i64 new_tmp_a64_zero(DisasContext *s)
{
TCGContext *tcg_ctx = s->uc->tcg_ctx;

View file

@ -30,6 +30,7 @@ void unallocated_encoding(DisasContext *s);
} while (0)
TCGv_i64 new_tmp_a64(DisasContext *s);
TCGv_i64 new_tmp_a64_local(DisasContext *s);
TCGv_i64 new_tmp_a64_zero(DisasContext *s);
TCGv_i64 cpu_reg(DisasContext *s, int reg);
TCGv_i64 cpu_reg_sp(DisasContext *s, int reg);

View file

@ -4521,9 +4521,8 @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
/* Copy the clean address into a local temp, live across the loop. */
t0 = clean_addr;
clean_addr = tcg_temp_local_new_i64(tcg_ctx);
clean_addr = new_tmp_a64_local(s);
tcg_gen_mov_i64(tcg_ctx, clean_addr, t0);
tcg_temp_free_i64(tcg_ctx, t0);
gen_set_label(tcg_ctx, loop);
@ -4571,7 +4570,6 @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
tcg_gen_st_i64(tcg_ctx, t0, tcg_ctx->cpu_env, vofs + len_align);
tcg_temp_free_i64(tcg_ctx, t0);
}
tcg_temp_free_i64(tcg_ctx, clean_addr);
}
/* Similarly for stores. */
@ -4613,9 +4611,8 @@ static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
/* Copy the clean address into a local temp, live across the loop. */
t0 = clean_addr;
clean_addr = tcg_temp_local_new_i64(tcg_ctx);
clean_addr = new_tmp_a64_local(s);
tcg_gen_mov_i64(tcg_ctx, clean_addr, t0);
tcg_temp_free_i64(tcg_ctx, t0);
gen_set_label(tcg_ctx, loop);
@ -4659,7 +4656,6 @@ static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
}
tcg_temp_free_i64(tcg_ctx, t0);
}
tcg_temp_free_i64(tcg_ctx, clean_addr);
}
static bool trans_LDR_zri(DisasContext *s, arg_rri *a)