aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2023-05-12 15:41:04 +0100
committerPeter Maydell <peter.maydell@linaro.org>2023-05-18 11:35:38 +0100
commit0ebbe9021254fb6db83780ac8b111e17b7ea2837 (patch)
tree856c389531879bf83b1101d3e9d54a8ef7feca82 /target
parentc0b5e3943b14298010384eb817b58458a97c5b22 (diff)
downloadqemu-0ebbe9021254fb6db83780ac8b111e17b7ea2837.zip
qemu-0ebbe9021254fb6db83780ac8b111e17b7ea2837.tar.gz
qemu-0ebbe9021254fb6db83780ac8b111e17b7ea2837.tar.bz2
target/arm: Convert BRA[AB]Z, BLR[AB]Z, RETA[AB] to decodetree
Convert the single-register pointer-authentication variants of BR, BLR, RET to decodetree. (BRAA/BLRAA are in a different branch of the legacy decoder and will be dealt with in the next commit.) Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20230512144106.3608981-19-peter.maydell@linaro.org
Diffstat (limited to 'target')
-rw-r--r--target/arm/tcg/a64.decode7
-rw-r--r--target/arm/tcg/translate-a64.c132
2 files changed, 84 insertions, 55 deletions
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
index 690dc10..f662020 100644
--- a/target/arm/tcg/a64.decode
+++ b/target/arm/tcg/a64.decode
@@ -131,3 +131,10 @@ B_cond 0101010 0 ................... 0 cond:4 imm=%imm19
BR 1101011 0000 11111 000000 rn:5 00000 &r
BLR 1101011 0001 11111 000000 rn:5 00000 &r
RET 1101011 0010 11111 000000 rn:5 00000 &r
+
+&braz rn m
+BRAZ 1101011 0000 11111 00001 m:1 rn:5 11111 &braz # BRAAZ, BRABZ
+BLRAZ 1101011 0001 11111 00001 m:1 rn:5 11111 &braz # BLRAAZ, BLRABZ
+
+&reta m
+RETA 1101011 0010 11111 00001 m:1 11111 11111 &reta # RETAA, RETAB
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 3af16e6..a278136 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -1435,6 +1435,75 @@ static bool trans_RET(DisasContext *s, arg_r *a)
return true;
}
+static TCGv_i64 auth_branch_target(DisasContext *s, TCGv_i64 dst,
+ TCGv_i64 modifier, bool use_key_a)
+{
+ TCGv_i64 truedst;
+ /*
+ * Return the branch target for a BRAA/RETA/etc, which is either
+ * just the destination dst, or that value with the pauth check
+ * done and the code removed from the high bits.
+ */
+ if (!s->pauth_active) {
+ return dst;
+ }
+
+ truedst = tcg_temp_new_i64();
+ if (use_key_a) {
+ gen_helper_autia(truedst, cpu_env, dst, modifier);
+ } else {
+ gen_helper_autib(truedst, cpu_env, dst, modifier);
+ }
+ return truedst;
+}
+
+static bool trans_BRAZ(DisasContext *s, arg_braz *a)
+{
+ TCGv_i64 dst;
+
+ if (!dc_isar_feature(aa64_pauth, s)) {
+ return false;
+ }
+
+ dst = auth_branch_target(s, cpu_reg(s, a->rn), tcg_constant_i64(0), !a->m);
+ gen_a64_set_pc(s, dst);
+ set_btype_for_br(s, a->rn);
+ s->base.is_jmp = DISAS_JUMP;
+ return true;
+}
+
+static bool trans_BLRAZ(DisasContext *s, arg_braz *a)
+{
+ TCGv_i64 dst, lr;
+
+ if (!dc_isar_feature(aa64_pauth, s)) {
+ return false;
+ }
+
+ dst = auth_branch_target(s, cpu_reg(s, a->rn), tcg_constant_i64(0), !a->m);
+ lr = cpu_reg(s, 30);
+ if (dst == lr) {
+ TCGv_i64 tmp = tcg_temp_new_i64();
+ tcg_gen_mov_i64(tmp, dst);
+ dst = tmp;
+ }
+ gen_pc_plus_diff(s, lr, curr_insn_len(s));
+ gen_a64_set_pc(s, dst);
+ set_btype_for_blr(s);
+ s->base.is_jmp = DISAS_JUMP;
+ return true;
+}
+
+static bool trans_RETA(DisasContext *s, arg_reta *a)
+{
+ TCGv_i64 dst;
+
+ dst = auth_branch_target(s, cpu_reg(s, 30), cpu_X[31], !a->m);
+ gen_a64_set_pc(s, dst);
+ s->base.is_jmp = DISAS_JUMP;
+ return true;
+}
+
/* HINT instruction group, including various allocated HINTs */
static void handle_hint(DisasContext *s, uint32_t insn,
unsigned int op1, unsigned int op2, unsigned int crm)
@@ -2227,61 +2296,14 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
}
switch (opc) {
- case 0: /* BR */
- case 1: /* BLR */
- case 2: /* RET */
- btype_mod = opc;
- switch (op3) {
- case 0:
- /* BR, BLR, RET : handled in decodetree */
- goto do_unallocated;
-
- case 2:
- case 3:
- if (!dc_isar_feature(aa64_pauth, s)) {
- goto do_unallocated;
- }
- if (opc == 2) {
- /* RETAA, RETAB */
- if (rn != 0x1f || op4 != 0x1f) {
- goto do_unallocated;
- }
- rn = 30;
- modifier = cpu_X[31];
- } else {
- /* BRAAZ, BRABZ, BLRAAZ, BLRABZ */
- if (op4 != 0x1f) {
- goto do_unallocated;
- }
- modifier = tcg_constant_i64(0);
- }
- if (s->pauth_active) {
- dst = tcg_temp_new_i64();
- if (op3 == 2) {
- gen_helper_autia(dst, cpu_env, cpu_reg(s, rn), modifier);
- } else {
- gen_helper_autib(dst, cpu_env, cpu_reg(s, rn), modifier);
- }
- } else {
- dst = cpu_reg(s, rn);
- }
- break;
-
- default:
- goto do_unallocated;
- }
- /* BLR also needs to load return address */
- if (opc == 1) {
- TCGv_i64 lr = cpu_reg(s, 30);
- if (dst == lr) {
- TCGv_i64 tmp = tcg_temp_new_i64();
- tcg_gen_mov_i64(tmp, dst);
- dst = tmp;
- }
- gen_pc_plus_diff(s, lr, curr_insn_len(s));
- }
- gen_a64_set_pc(s, dst);
- break;
+ case 0:
+ case 1:
+ case 2:
+ /*
+ * BR, BLR, RET, RETAA, RETAB, BRAAZ, BRABZ, BLRAAZ, BLRABZ:
+ * handled in decodetree
+ */
+ goto do_unallocated;
case 8: /* BRAA */
case 9: /* BLRAA */