Signed-off-by: Richard Henderson richard.henderson@linaro.org --- target/arm/translate-a64.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-)
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 9820a9b745..fcce1f3a9e 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -138,6 +138,19 @@ static void reset_btype(DisasContext *s) } }
+static void set_btype(DisasContext *s, int val) +{ + TCGv_i32 tcg_val; + + /* BTYPE is a 2-bit field, and 0 should be done with reset_btype. */ + tcg_debug_assert(val >= 1 && val <= 3); + + tcg_val = tcg_const_i32(val); + tcg_gen_st_i32(tcg_val, cpu_env, offsetof(CPUARMState, btype)); + tcg_temp_free_i32(tcg_val); + s->btype = -1; +} + void aarch64_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, int flags) { @@ -1984,6 +1997,7 @@ static void disas_exc(DisasContext *s, uint32_t insn) static void disas_uncond_b_reg(DisasContext *s, uint32_t insn) { unsigned int opc, op2, op3, rn, op4; + unsigned btype_mod = 2; TCGv_i64 dst; TCGv_i64 modifier;
@@ -2001,6 +2015,7 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn) case 0: /* BR */ case 1: /* BLR */ case 2: /* RET */ + btype_mod = opc; switch (op3) { case 0: /* BR, BLR, RET */ @@ -2044,7 +2059,6 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn) default: goto do_unallocated; } - gen_a64_set_pc(s, dst); /* BLR also needs to load return address */ if (opc == 1) { @@ -2060,6 +2074,7 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn) if (op3 != 2 || op3 != 3) { goto do_unallocated; } + btype_mod = opc & 1; if (s->pauth_active) { dst = new_tmp_a64(s); modifier = cpu_reg_sp(s, op4); @@ -2143,6 +2158,26 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn) return; }
+ switch (btype_mod) { + case 0: /* BR */ + if (dc_isar_feature(aa64_bti, s)) { + /* BR to {x16,x17} or !guard -> 1, else 3. */ + set_btype(s, rn == 16 || rn == 17 || !s->guarded_page ? 1 : 3); + } + break; + + case 1: /* BLR */ + if (dc_isar_feature(aa64_bti, s)) { + /* BLR sets BTYPE to 2, regardless of source guarded page. */ + set_btype(s, 2); + } + break; + + default: /* RET or none of the above. */ + /* BTYPE will be set to 0 by normal end-of-insn processing. */ + break; + } + s->base.is_jmp = DISAS_JUMP; }