All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v5 2/2] target-arm: Implement ARMv8 VSEL instruction.
@ 2013-10-15 15:09 Will Newton
  0 siblings, 0 replies; only message in thread
From: Will Newton @ 2013-10-15 15:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Patch Tracking


This adds support for the VSEL floating point selection instruction
which was added in ARMv8.

Signed-off-by: Will Newton <will.newton@linaro.org>
---
 target-arm/translate.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 129 insertions(+), 1 deletion(-)

Changes in v5:
 - Break out VSEL decode into separate disas_vfp_v8_insn function

diff --git a/target-arm/translate.c b/target-arm/translate.c
index c04d2cf..2b4020f 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -2614,6 +2614,134 @@ static TCGv_i32 gen_load_and_replicate(DisasContext *s, TCGv_i32 addr, int size)
     return tmp;
 }

+static int disas_vfp_v8_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
+{
+    uint32_t rd, rn, rm, dp = (insn >> 8) & 1;
+
+    if (!arm_feature(env, ARM_FEATURE_V8)) {
+        return 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 & 0x0f800e50) == 0x0e000a00) {
+        /* vsel */
+        uint32_t cc = (insn >> 20) & 3;
+
+        if (dp) {
+            TCGv_i64 ftmp1, ftmp2, ftmp3;
+            TCGv_i64 tmp, zero, zf, nf, vf;
+
+            zero = tcg_const_i64(0);
+
+            ftmp1 = tcg_temp_new_i64();
+            ftmp2 = tcg_temp_new_i64();
+            ftmp3 = tcg_temp_new_i64();
+
+            zf = tcg_temp_new_i64();
+            nf = tcg_temp_new_i64();
+            vf = tcg_temp_new_i64();
+
+            tcg_gen_extu_i32_i64(zf, cpu_ZF);
+            tcg_gen_extu_i32_i64(nf, cpu_NF);
+            tcg_gen_extu_i32_i64(vf, cpu_VF);
+
+            tcg_gen_ld_f64(ftmp1, cpu_env, vfp_reg_offset(dp, rn));
+            tcg_gen_ld_f64(ftmp2, cpu_env, vfp_reg_offset(dp, rm));
+            switch (cc) {
+            case 0: /* eq: Z */
+                tcg_gen_movcond_i64(TCG_COND_EQ, ftmp3, zf, zero,
+                                    ftmp1, ftmp2);
+                break;
+            case 1: /* vs: V */
+                tcg_gen_movcond_i64(TCG_COND_LT, ftmp3, vf, zero,
+                                    ftmp1, ftmp2);
+                break;
+            case 2: /* ge: N == V -> N ^ V == 0 */
+                tmp = tcg_temp_new_i64();
+                tcg_gen_xor_i64(tmp, vf, nf);
+                tcg_gen_movcond_i64(TCG_COND_GE, ftmp3, tmp, zero,
+                                    ftmp1, ftmp2);
+                tcg_temp_free_i64(tmp);
+                break;
+            case 3: /* gt: !Z && N == V */
+                tcg_gen_movcond_i64(TCG_COND_NE, ftmp3, zf, zero,
+                                    ftmp1, ftmp2);
+                tmp = tcg_temp_new_i64();
+                tcg_gen_xor_i64(tmp, vf, nf);
+                tcg_gen_movcond_i64(TCG_COND_GE, ftmp3, tmp, zero,
+                                    ftmp3, ftmp2);
+                tcg_temp_free_i64(tmp);
+                break;
+            }
+            tcg_gen_st_f64(ftmp3, cpu_env, vfp_reg_offset(dp, rd));
+            tcg_temp_free_i64(ftmp1);
+            tcg_temp_free_i64(ftmp2);
+            tcg_temp_free_i64(ftmp3);
+
+            tcg_temp_free_i64(zf);
+            tcg_temp_free_i64(nf);
+            tcg_temp_free_i64(vf);
+
+            tcg_temp_free_i64(zero);
+        } else {
+            TCGv_i32 ftmp1, ftmp2, ftmp3;
+            TCGv_i32 tmp, zero;
+
+            zero = tcg_const_i32(0);
+
+            ftmp1 = tcg_temp_new_i32();
+            ftmp2 = tcg_temp_new_i32();
+            ftmp3 = tcg_temp_new_i32();
+            tcg_gen_ld_f32(ftmp1, cpu_env, vfp_reg_offset(dp, rn));
+            tcg_gen_ld_f32(ftmp2, cpu_env, vfp_reg_offset(dp, rm));
+            switch (cc) {
+            case 0: /* eq: Z */
+                tcg_gen_movcond_i32(TCG_COND_EQ, ftmp3, cpu_ZF, zero,
+                                    ftmp1, ftmp2);
+                break;
+            case 1: /* vs: V */
+                tcg_gen_movcond_i32(TCG_COND_LT, ftmp3, cpu_VF, zero,
+                                    ftmp1, ftmp2);
+                break;
+            case 2: /* ge: N == V -> N ^ V == 0 */
+                tmp = tcg_temp_new_i32();
+                tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
+                tcg_gen_movcond_i32(TCG_COND_GE, ftmp3, tmp, zero,
+                                    ftmp1, ftmp2);
+                tcg_temp_free_i32(tmp);
+                break;
+            case 3: /* gt: !Z && N == V */
+                tcg_gen_movcond_i32(TCG_COND_NE, ftmp3, cpu_ZF, zero,
+                                    ftmp1, ftmp2);
+                tmp = tcg_temp_new_i32();
+                tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
+                tcg_gen_movcond_i32(TCG_COND_GE, ftmp3, tmp, zero,
+                                    ftmp3, ftmp2);
+                tcg_temp_free_i32(tmp);
+                break;
+            }
+            tcg_gen_st_f32(ftmp3, cpu_env, vfp_reg_offset(dp, rd));
+            tcg_temp_free_i32(ftmp1);
+            tcg_temp_free_i32(ftmp2);
+            tcg_temp_free_i32(ftmp3);
+
+            tcg_temp_free_i32(zero);
+        }
+
+        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)
@@ -2640,7 +2768,7 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
     if (extract32(insn, 28, 4) == 0xf) {
         /* Encodings with T=1 (Thumb) or unconditional (ARM):
            only used in v8 and above.  */
-        return 1;
+        return disas_vfp_v8_insn(env, s, insn);
     }

     dp = ((insn & 0xf00) == 0xb00);
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2013-10-15 15:09 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-10-15 15:09 [Qemu-devel] [PATCH v5 2/2] target-arm: Implement ARMv8 VSEL instruction Will Newton

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.