qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH] target-arm: implement ARMv8 VSEL instruction


From: Mans Rullgard
Subject: [Qemu-devel] [PATCH] target-arm: implement ARMv8 VSEL instruction
Date: Tue, 18 Jun 2013 15:30:48 +0100

This adds support for the VSEL instruction introduced in ARMv8.
It resides along with other new VFP instructions under the CDP2
encoding which was previously unused.

Signed-off-by: Mans Rullgard <address@hidden>
---
Basic testing performed but not every combination.
---
 target-arm/translate.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 49 insertions(+), 2 deletions(-)

diff --git a/target-arm/translate.c b/target-arm/translate.c
index f7089b2..eb9423b 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -2546,6 +2546,40 @@ static TCGv_i32 gen_load_and_replicate(DisasContext *s, 
TCGv_i32 addr, int size)
     return tmp;
 }
 
+static int disas_v8vfp_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
+{
+    uint32_t rd, rn, rm;
+    int dp = (insn >> 8) & 1;
+
+    if (dp) {
+        VFP_DREG_D(rd, insn);
+        VFP_DREG_N(rn, insn);
+        VFP_DREG_M(rm, insn);
+    } else {
+        rd = VFP_SREG_D(insn);
+        rn = VFP_SREG_N(insn);
+        rm = VFP_SREG_M(insn);
+    }
+
+    if (((insn >> 23) & 1) == 0) {
+        /* vsel */
+        int cc = (insn >> 20) & 3;
+        int cond = (cc << 2) | (((cc << 1) ^ cc) & 2);
+        int pass_label = gen_new_label();
+
+        gen_mov_F0_vreg(dp, rn);
+        gen_mov_vreg_F0(dp, rd);
+        gen_test_cc(cond, pass_label);
+        gen_mov_F0_vreg(dp, rm);
+        gen_mov_vreg_F0(dp, rd);
+        gen_set_label(pass_label);
+
+        return 0;
+    }
+
+    return 1;
+}
+
 /* Disassemble a VFP instruction.  Returns nonzero if an error occurred
    (ie. an undefined instruction).  */
 static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
@@ -2568,6 +2602,11 @@ static int disas_vfp_insn(CPUARMState * env, 
DisasContext *s, uint32_t insn)
             && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
             return 1;
     }
+    if (((insn >> 28) & 0xf) == 0xf) {
+        if (!arm_feature(env, ARM_FEATURE_V8))
+            return 1;
+        return disas_v8vfp_insn(env, s, insn);
+    }
     dp = ((insn & 0xf00) == 0xb00);
     switch ((insn >> 24) & 0xf) {
     case 0xe:
@@ -6241,6 +6280,10 @@ static int disas_coproc_insn(CPUARMState * env, 
DisasContext *s, uint32_t insn)
         /* cdp */
         return 1;
     }
+    if (((insn >> 28) & 0xf) == 0xf) {
+        /* cdp2 */
+        return 1;
+    }
 
     crm = insn & 0xf;
     if (is64) {
@@ -6699,6 +6742,12 @@ static void disas_arm_insn(CPUARMState * env, 
DisasContext *s)
             }
             return; /* v7MP: Unallocated memory hint: must NOP */
         }
+        if ((insn & 0x0f000010) == 0x0e000000) {
+            /* cdp2 */
+            if (disas_coproc_insn(env, s, insn))
+                goto illegal_op;
+            return;
+        }
 
         if ((insn & 0x0ffffdff) == 0x01010000) {
             ARCH(6);
@@ -8684,8 +8733,6 @@ static int disas_thumb2_insn(CPUARMState *env, 
DisasContext *s, uint16_t insn_hw
             if (disas_neon_data_insn(env, s, insn))
                 goto illegal_op;
         } else {
-            if (insn & (1 << 28))
-                goto illegal_op;
             if (disas_coproc_insn (env, s, insn))
                 goto illegal_op;
         }
-- 
1.8.2.1




reply via email to

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