diff mbox

[40/60] AArch64: Add tbz instruction emulation

Message ID 1380242934-20953-41-git-send-email-agraf@suse.de
State New
Headers show

Commit Message

Alexander Graf Sept. 27, 2013, 12:48 a.m. UTC
This patch adds emulation for the tbz/tbnz instructions.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 target-arm/translate-a64.c | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

Comments

Richard Henderson Sept. 27, 2013, 8:50 p.m. UTC | #1
On 09/26/2013 05:48 PM, Alexander Graf wrote:
> +    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);
> +    }

You'd do better to brcond vs zero after the and.


r~
diff mbox

Patch

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;