aboutsummaryrefslogtreecommitdiff
path: root/target-arm/translate-a64.c
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2013-12-17 19:42:33 +0000
committerPeter Maydell <peter.maydell@linaro.org>2013-12-17 19:42:33 +0000
commit39fb730aed8c5f7b0058845cb9feac0d4b177985 (patch)
tree82ec795502c06f01ffe0dc99e9c9fbe4daf49631 /target-arm/translate-a64.c
parentb001c8c3d6855b0b52fc0fdd63b5a93fd326bf0c (diff)
target-arm: A64: add support for conditional branches
This patch adds emulation for the conditional branch (b.cond) instruction. Signed-off-by: Alexander Graf <agraf@suse.de> [claudio: adapted to new decoder structure, reused arm infrastructure for checking the flags] 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/translate-a64.c')
-rw-r--r--target-arm/translate-a64.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index b69466585f..4eb2992754 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -239,10 +239,35 @@ static void disas_test_b_imm(DisasContext *s, uint32_t insn)
unsupported_encoding(s, insn);
}
-/* Conditional branch (immediate) */
+/* C3.2.2 / C5.6.19 Conditional branch (immediate)
+ * 31 25 24 23 5 4 3 0
+ * +---------------+----+---------------------+----+------+
+ * | 0 1 0 1 0 1 0 | o1 | imm19 | o0 | cond |
+ * +---------------+----+---------------------+----+------+
+ */
static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
{
- unsupported_encoding(s, insn);
+ unsigned int cond;
+ uint64_t addr;
+
+ if ((insn & (1 << 4)) || (insn & (1 << 24))) {
+ unallocated_encoding(s);
+ return;
+ }
+ addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
+ cond = extract32(insn, 0, 4);
+
+ if (cond < 0x0e) {
+ /* genuinely conditional branches */
+ int label_match = gen_new_label();
+ arm_gen_test_cc(cond, label_match);
+ gen_goto_tb(s, 0, s->pc);
+ gen_set_label(label_match);
+ gen_goto_tb(s, 1, addr);
+ } else {
+ /* 0xe and 0xf are both "always" conditions */
+ gen_goto_tb(s, 0, addr);
+ }
}
/* C5.6.68 HINT */