summaryrefslogtreecommitdiffstats
path: root/target-arm
diff options
context:
space:
mode:
authorAlexander Graf2013-12-17 20:42:33 +0100
committerPeter Maydell2013-12-17 20:42:33 +0100
commitb001c8c3d6855b0b52fc0fdd63b5a93fd326bf0c (patch)
tree23f6ef2615c1ad87282d9caedcea85ab6cae1e75 /target-arm
parenttarget-arm: A64: add support for B and BL insns (diff)
downloadqemu-b001c8c3d6855b0b52fc0fdd63b5a93fd326bf0c.tar.gz
qemu-b001c8c3d6855b0b52fc0fdd63b5a93fd326bf0c.tar.xz
qemu-b001c8c3d6855b0b52fc0fdd63b5a93fd326bf0c.zip
target-arm: A64: add support for BR, BLR and RET insns
Implement BR, BLR and RET. This is all of the 'unconditional branch (register)' instruction category except for ERET and DPRS (which are system mode only). Signed-off-by: Alexander Graf <agraf@suse.de> [claudio: reimplemented on top of new decoder structure] Signed-off-by: Claudio Fontana <claudio.fontana@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <rth@twiddle.net>
Diffstat (limited to 'target-arm')
-rw-r--r--target-arm/translate-a64.c43
1 files changed, 41 insertions, 2 deletions
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index ead5658d46..b69466585f 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -384,10 +384,49 @@ static void disas_exc(DisasContext *s, uint32_t insn)
unsupported_encoding(s, insn);
}
-/* Unconditional branch (register) */
+/* C3.2.7 Unconditional branch (register)
+ * 31 25 24 21 20 16 15 10 9 5 4 0
+ * +---------------+-------+-------+-------+------+-------+
+ * | 1 1 0 1 0 1 1 | opc | op2 | op3 | Rn | op4 |
+ * +---------------+-------+-------+-------+------+-------+
+ */
static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
{
- unsupported_encoding(s, insn);
+ unsigned int opc, op2, op3, rn, op4;
+
+ opc = extract32(insn, 21, 4);
+ op2 = extract32(insn, 16, 5);
+ op3 = extract32(insn, 10, 6);
+ rn = extract32(insn, 5, 5);
+ op4 = extract32(insn, 0, 5);
+
+ if (op4 != 0x0 || op3 != 0x0 || op2 != 0x1f) {
+ unallocated_encoding(s);
+ return;
+ }
+
+ switch (opc) {
+ case 0: /* BR */
+ case 2: /* RET */
+ break;
+ case 1: /* BLR */
+ tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
+ break;
+ case 4: /* ERET */
+ case 5: /* DRPS */
+ if (rn != 0x1f) {
+ unallocated_encoding(s);
+ } else {
+ unsupported_encoding(s, insn);
+ }
+ return;
+ default:
+ unallocated_encoding(s);
+ return;
+ }
+
+ tcg_gen_mov_i64(cpu_pc, cpu_reg(s, rn));
+ s->is_jmp = DISAS_JUMP;
}
/* C3.2 Branches, exception generating and system instructions */