Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/tcg/translate-a64.c | 29 ++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 529c5bef0c..462c61032b 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -444,6 +444,27 @@ static void gen_add_gcs_record(DisasContext *s, TCGv_i64 value)
tcg_gen_mov_i64(gcspr, addr);
}
+static void gen_load_check_gcs_record(DisasContext *s, TCGv_i64 target,
+ GCSInstructionType it, int rt)
+{
+ TCGv_i64 gcspr = cpu_gcspr[s->current_el];
+ int mmuidx = core_gcs_mem_index(s->mmu_idx);
+ MemOp mop = finalize_memop(s, MO_64 | MO_ALIGN);
+ TCGv_i64 rec_va = tcg_temp_new_i64();
+
+ tcg_gen_qemu_ld_i64(rec_va, clean_data_tbi(s, gcspr), 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(gcspr, gcspr, 8);
+}
+
typedef struct DisasCompare64 {
TCGCond cond;
TCGv_i64 value;
@@ -1798,7 +1819,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