This patch adds emulation for compare and branch instructions (cbz, cbnz) Signed-off-by: Alexander Graf <ag...@suse.de> --- target-arm/translate-a64.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index fdcf876..229b467 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -233,6 +233,41 @@ static void handle_br(DisasContext *s, uint32_t insn) s->is_jmp = DISAS_JUMP; } +static void handle_cb(DisasContext *s, uint32_t insn) +{ + uint64_t addr = s->pc - 4 + (get_sbits(insn, 5, 19) << 2); + bool is_zero = !get_bits(insn, 24, 1); + bool is_32bit = !get_bits(insn, 31, 1); + int dest = get_reg(insn); + int no_match; + TCGv_i64 tcg_cmp, tcg_zero; + + tcg_cmp = tcg_temp_new_i64(); + tcg_zero = tcg_const_i64(0); + + if (is_32bit) { + tcg_gen_ext32u_i64(tcg_cmp, cpu_reg(dest)); + } else { + tcg_gen_mov_i64(tcg_cmp, cpu_reg(dest)); + } + + no_match = gen_new_label(); + if (is_zero) { + tcg_gen_brcond_i64(TCG_COND_NE, tcg_cmp, tcg_zero, no_match); + } else { + tcg_gen_brcond_i64(TCG_COND_EQ, tcg_cmp, tcg_zero, no_match); + } + gen_goto_tb(s, 0, addr); + + gen_set_label(no_match); + gen_goto_tb(s, 1, s->pc); + + s->is_jmp = DISAS_TB_JUMP; + + tcg_temp_free_i64(tcg_cmp); + tcg_temp_free_i64(tcg_zero); +} + static void ldst_do_vec_int(DisasContext *s, int freg_offs, TCGv_i64 tcg_addr, int size, bool is_store) { @@ -1706,6 +1741,15 @@ void disas_a64_insn(CPUARMState *env, DisasContext *s) case 0x14: if (get_bits(insn, 29, 3) == 0x6 && !get_bits(insn, 2, 3)) { handle_svc(s, insn); + } else if (get_bits(insn, 29, 2) == 0x1) { + handle_cb(s, insn); + } else { + unallocated_encoding(s); + } + break; + case 0x15: + if (get_bits(insn, 29, 2) == 0x1) { + handle_cb(s, insn); } else { unallocated_encoding(s); } -- 1.7.12.4