This patch adds emulation for the tbz/tbnz instructions. Signed-off-by: Alexander Graf <ag...@suse.de> --- target-arm/translate-a64.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+)
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 2c2adb8..7232cf4 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -294,6 +294,38 @@ static void handle_condb(DisasContext *s, uint32_t insn) s->is_jmp = DISAS_TB_JUMP; } +static void handle_tbz(DisasContext *s, uint32_t insn) +{ + uint64_t addr = s->pc - 4 + (get_sbits(insn, 5, 14) << 2); + bool is_one = get_bits(insn, 24, 1); + int shift = get_bits(insn, 19, 5) | (get_bits(insn, 31, 1) << 5); + int source = get_reg(insn); + int no_match; + uint64_t mask = 1ULL << shift; + TCGv_i64 tcg_cmp, tcg_mask; + + tcg_cmp = tcg_temp_new_i64(); + tcg_mask = tcg_const_i64(mask); + tcg_gen_and_i64(tcg_cmp, cpu_reg(source), tcg_mask); + + no_match = gen_new_label(); + if (is_one) { + tcg_gen_brcond_i64(TCG_COND_NE, tcg_cmp, tcg_mask, no_match); + } else { + tcg_gen_brcond_i64(TCG_COND_EQ, tcg_cmp, tcg_mask, no_match); + } + gen_goto_tb(s, 0, addr); + tcg_gen_exit_tb(0); + + gen_set_label(no_match); + gen_goto_tb(s, 1, s->pc); + + tcg_temp_free_i64(tcg_cmp); + tcg_temp_free_i64(tcg_mask); + + s->is_jmp = DISAS_TB_JUMP; +} + static void ldst_do_vec_int(DisasContext *s, int freg_offs, TCGv_i64 tcg_addr, int size, bool is_store) { @@ -1856,6 +1888,14 @@ void disas_a64_insn(CPUARMState *env, DisasContext *s) unallocated_encoding(s); } break; + case 0x16: + case 0x17: + if (get_bits(insn, 29, 2) == 0x1) { + handle_tbz(s, insn); + } else { + unallocated_encoding(s); + } + break; default: unallocated_encoding(s); break; -- 1.7.12.4