qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 44/60] AArch64: Add division instruction family emul


From: Alexander Graf
Subject: [Qemu-devel] [PATCH 44/60] AArch64: Add division instruction family emulation
Date: Fri, 27 Sep 2013 02:48:38 +0200

This patch adds emulation support for the udiv and sdiv instructions.

Signed-off-by: Alexander Graf <address@hidden>
---
 target-arm/helper-a64.c    | 16 ++++++++++++++++
 target-arm/helper-a64.h    |  2 ++
 target-arm/translate-a64.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 61 insertions(+)

diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index 3f055b6..a56ce75 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -221,3 +221,19 @@ out:
 
     return r;
 }
+
+uint64_t HELPER(udiv64)(uint64_t num, uint64_t den)
+{
+    if (den == 0)
+      return 0;
+    return num / den;
+}
+
+int64_t HELPER(sdiv64)(int64_t num, int64_t den)
+{
+    if (den == 0)
+      return 0;
+    if (num == LLONG_MIN && den == -1)
+      return LLONG_MIN;
+    return num / den;
+}
diff --git a/target-arm/helper-a64.h b/target-arm/helper-a64.h
index 8874518..ad1a94a 100644
--- a/target-arm/helper-a64.h
+++ b/target-arm/helper-a64.h
@@ -24,3 +24,5 @@ DEF_HELPER_FLAGS_4(pstate_sub32, TCG_CALL_NO_RWG_SE, i32, 
i32, i64, i64, i64)
 DEF_HELPER_FLAGS_3(sign_extend, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
 DEF_HELPER_FLAGS_2(cond, TCG_CALL_NO_RWG_SE, i32, i32, i32)
 DEF_HELPER_FLAGS_4(cinc, TCG_CALL_NO_RWG_SE, i64, i32, i32, i64, i64)
+DEF_HELPER_FLAGS_2(udiv64, TCG_CALL_NO_RWG_SE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(sdiv64, TCG_CALL_NO_RWG_SE, s64, s64, s64)
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index cd2dfe6..6954ff7 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1507,6 +1507,47 @@ static void handle_cinc(DisasContext *s, uint32_t insn)
     gen_helper_cinc(cpu_reg(rd), pstate, tcg_insn, cpu_reg(rn), cpu_reg(rm));
 }
 
+static void handle_div(DisasContext *s, uint32_t insn)
+{
+    int rd = get_reg(insn);
+    int rn = get_bits(insn, 5, 5);
+    int rm = get_bits(insn, 16, 5);
+    bool is_signed = get_bits(insn, 10, 1);
+    bool is_32bit = !get_bits(insn, 31, 1);
+    TCGv_i64 n = tcg_temp_new_i64();
+    TCGv_i64 m = tcg_temp_new_i64();
+
+    if (is_32bit) {
+        if (is_signed) {
+            tcg_gen_ext32s_i64(n, cpu_reg(rn));
+            tcg_gen_ext32s_i64(m, cpu_reg(rm));
+        } else {
+            tcg_gen_ext32u_i64(n, cpu_reg(rn));
+            tcg_gen_ext32u_i64(m, cpu_reg(rm));
+        }
+    } else {
+        tcg_gen_mov_i64(n, cpu_reg(rn));
+        tcg_gen_mov_i64(m, cpu_reg(rm));
+    }
+
+    if (is_signed) {
+        gen_helper_sdiv64(cpu_reg(rd), n, m);
+    } else {
+        gen_helper_udiv64(cpu_reg(rd), n, m);
+    }
+
+    if (is_32bit) {
+        if (is_signed) {
+            tcg_gen_ext32s_i64(cpu_reg(rd), cpu_reg(rd));
+        } else {
+            tcg_gen_ext32u_i64(cpu_reg(rd), cpu_reg(rd));
+        }
+    }
+
+    tcg_temp_free_i64(n);
+    tcg_temp_free_i64(m);
+}
+
 /* SIMD ORR */
 static void handle_simdorr(DisasContext *s, uint32_t insn)
 {
@@ -2069,6 +2110,8 @@ void disas_a64_insn(CPUARMState *env, DisasContext *s)
     case 0x1a:
         if ((insn & 0x3fe00800) == 0x1a800000) {
             handle_cinc(s, insn);
+        } else if ((insn & 0x7fe0f800) == 0x1ac00800) {
+            handle_div(s, insn);
         } else {
             unallocated_encoding(s);
         }
-- 
1.7.12.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]