Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/tcg/translate-a64.c | 32 +++++++++++++++++++++++++++++++-
1 file changed, 31 insertions(+), 1 deletion(-)
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index a945fd3b33..49e17548c1 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -433,6 +433,30 @@ static void gen_add_gcs_record(DisasContext *s, TCGv_i64 value)
tcg_gen_st_i64(addr, tcg_env, sp_off);
}
+static void gen_load_check_gcs_record(DisasContext *s, TCGv_i64 target,
+ GCSInstructionType it, int rt)
+{
+ int sp_off = offsetof(CPUARMState, cp15.gcspr_el[s->current_el]);
+ int mmuidx = core_gcs_mem_index(s->mmu_idx);
+ MemOp mop = finalize_memop(s, MO_64 | MO_ALIGN);
+ TCGv_i64 addr = tcg_temp_new_i64();
+ TCGv_i64 rec_va = tcg_temp_new_i64();
+
+ tcg_gen_ld_i64(addr, tcg_env, sp_off);
+ tcg_gen_qemu_ld_i64(rec_va, clean_data_tbi(s, addr), mmuidx, mop);
+
+ if (s->gcs_rvcen) {
+ TCGLabel *fail_label =
+ delay_exception(s, EXCP_UDEF, syn_gcs_data_check(it, rt));
+
+ tcg_gen_brcond_i64(TCG_COND_NE, rec_va, target, fail_label);
+ }
+
+ gen_a64_set_pc(s, rec_va);
+ tcg_gen_addi_i64(addr, addr, 8);
+ tcg_gen_st_i64(addr, tcg_env, sp_off);
+}
+
typedef struct DisasCompare64 {
TCGCond cond;
TCGv_i64 value;
@@ -1787,7 +1811,13 @@ static bool trans_BLR(DisasContext *s, arg_r *a)
static bool trans_RET(DisasContext *s, arg_r *a)
{
- gen_a64_set_pc(s, cpu_reg(s, a->rn));
+ TCGv_i64 target = cpu_reg(s, a->rn);
+
+ if (s->gcs_en) {
+ gen_load_check_gcs_record(s, target, GCS_IT_RET_nPauth, a->rn);
+ } else {
+ gen_a64_set_pc(s, target);
+ }
s->base.is_jmp = DISAS_JUMP;
return true;
}
--
2.43.0