qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 53/60] AArch64: Add "Floating-point compare" instruc


From: Alexander Graf
Subject: [Qemu-devel] [PATCH 53/60] AArch64: Add "Floating-point compare" instruction
Date: Fri, 27 Sep 2013 02:48:47 +0200

This patch adds support for instructions that belong to the "Floating-point
compare" group of instructions.

Signed-off-by: Alexander Graf <address@hidden>
---
 target-arm/translate-a64.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index cc35c4e..948e5c4 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1975,6 +1975,69 @@ static void handle_fpintconv(DisasContext *s, uint32_t 
insn)
     }
 }
 
+/* Floating-point compare */
+static void handle_fcmp(DisasContext *s, uint32_t insn)
+{
+    int opc = get_bits(insn, 3, 2);
+    int rn = get_bits(insn, 5, 5);
+    int rm = get_bits(insn, 16, 5);
+    bool is_32bit = !get_bits(insn, 22, 1);
+    bool is_cmp_with_zero = get_bits(opc, 0, 1);
+    int freg_offs_n = offsetof(CPUARMState, vfp.regs[rn * 2]);
+    int freg_offs_m = offsetof(CPUARMState, vfp.regs[rm * 2]);
+    TCGv_i32 tcg_op1_32 = tcg_temp_new_i32();
+    TCGv_i32 tcg_op1_64 = tcg_temp_new_i64();
+    TCGv_i32 tcg_op2_32;
+    TCGv_i32 tcg_op2_64;
+
+    if (get_bits(insn, 23, 1)) {
+        unallocated_encoding(s);
+    }
+
+    tcg_gen_ld_i64(tcg_op1_64, cpu_env, freg_offs_n);
+
+    if (is_32bit) {
+        tcg_gen_trunc_i64_i32(tcg_op1_32, tcg_op1_64);
+    }
+
+    if (is_cmp_with_zero) {
+        tcg_op2_32 = tcg_const_i32(0);
+        tcg_op2_64 = tcg_const_i64(0);
+    } else {
+        tcg_op2_32 = tcg_temp_new_i32();
+        tcg_op2_64 = tcg_temp_new_i64();
+
+        tcg_gen_ld_i64(tcg_op2_64, cpu_env, freg_offs_m);
+        if (is_32bit) {
+            tcg_gen_trunc_i64_i32(tcg_op2_32, tcg_op2_64);
+        }
+    }
+
+    switch (opc | (is_32bit ? 0x0 : 0x4)) {
+    case 0x0: /* FCMP single, 32bit */
+    case 0x1: /* FCMPZ single, 32bit */
+        gen_helper_vfp_cmps(pstate, tcg_op1_32, tcg_op2_32, cpu_env);
+        break;
+    case 0x2: /* FCMPE single, 32bit */
+    case 0x3: /* FCMPEZ single, 32bit */
+        gen_helper_vfp_cmpes(pstate, tcg_op1_32, tcg_op2_32, cpu_env);
+        break;
+    case 0x4: /* FCMP double, 64bit */
+    case 0x5: /* FCMPZ double, 64bit */
+        gen_helper_vfp_cmpd(pstate, tcg_op1_64, tcg_op2_64, cpu_env);
+        break;
+    case 0x6: /* FCMPE double, 64bit */
+    case 0x7: /* FCMPEZ double, 64bit */
+        gen_helper_vfp_cmped(pstate, tcg_op1_64, tcg_op2_64, cpu_env);
+        break;
+    }
+
+    tcg_temp_free_i64(tcg_op1_64);
+    tcg_temp_free_i64(tcg_op2_64);
+    tcg_temp_free_i32(tcg_op1_32);
+    tcg_temp_free_i32(tcg_op2_32);
+}
+
 /* SIMD ORR */
 static void handle_simdorr(DisasContext *s, uint32_t insn)
 {
@@ -2563,6 +2626,9 @@ void disas_a64_insn(CPUARMState *env, DisasContext *s)
         } else if (get_bits(insn, 21, 1) && !get_bits(insn, 30, 1) &&
                    !get_bits(insn, 10, 6)) {
             handle_fpintconv(s, insn);
+        } else if (!get_bits(insn, 29, 3) && get_bits(insn, 21, 1) &&
+                   (get_bits(insn, 10, 6) == 0x8) && !get_bits(insn, 0, 3)) {
+            handle_fcmp(s, insn);
         } else {
             unallocated_encoding(s);
         }
-- 
1.7.12.4




reply via email to

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