qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v8 0/6] target-arm: Add support for VSEL and VMIN/MAXNM.
@ 2013-12-04 11:54 Will Newton
  2013-12-04 11:54 ` [Qemu-devel] [PATCH v8 1/6] target-arm: Move call to disas_vfp_insn out of disas_coproc_insn Will Newton
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Will Newton @ 2013-12-04 11:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: patches

This series adds support for three new instructions added in ARMv8 -
VSEL, VMINNM and VMAXNM.

Will Newton (6):
  target-arm: Move call to disas_vfp_insn out of disas_coproc_insn.
  target-arm: Implement ARMv8 VSEL instruction.
  softfloat: Remove unused argument from MINMAX macro.
  softfloat: Add minNum() and maxNum() functions to softfloat.
  target-arm: Implement ARMv8 FP VMAXNM and VMINNM instructions.
  target-arm: Implement ARMv8 SIMD VMAXNM and VMINNM instructions.

 fpu/softfloat.c         |  38 ++++++--
 include/fpu/softfloat.h |   4 +
 target-arm/helper.c     |  25 +++++
 target-arm/helper.h     |   5 +
 target-arm/translate.c  | 246 +++++++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 298 insertions(+), 20 deletions(-)

-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PATCH v8 1/6] target-arm: Move call to disas_vfp_insn out of disas_coproc_insn.
  2013-12-04 11:54 [Qemu-devel] [PATCH v8 0/6] target-arm: Add support for VSEL and VMIN/MAXNM Will Newton
@ 2013-12-04 11:54 ` Will Newton
  2013-12-04 11:54 ` [Qemu-devel] [PATCH v8 2/6] target-arm: Implement ARMv8 VSEL instruction Will Newton
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Will Newton @ 2013-12-04 11:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: patches

Floating point is an extension to the instruction set rather than
a coprocessor, so call it directly from the ARM and Thumb decode
functions.

Signed-off-by: Will Newton <will.newton@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/translate.c | 32 +++++++++++++++++++++++++++-----
 1 file changed, 27 insertions(+), 5 deletions(-)

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 5f003e7..f63e89d 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -2636,6 +2636,14 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
             && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
             return 1;
     }
+
+    if (extract32(insn, 28, 4) == 0xf) {
+        /* Encodings with T=1 (Thumb) or unconditional (ARM):
+         * only used in v8 and above.
+         */
+        return 1;
+    }
+
     dp = ((insn & 0xf00) == 0xb00);
     switch ((insn >> 24) & 0xf) {
     case 0xe:
@@ -6296,9 +6304,6 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
 	    return disas_dsp_insn(env, s, insn);
 	}
 	return 1;
-    case 10:
-    case 11:
-	return disas_vfp_insn (env, s, insn);
     default:
         break;
     }
@@ -6753,6 +6758,13 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
                 goto illegal_op;
             return;
         }
+        if ((insn & 0x0f000e10) == 0x0e000a00) {
+            /* VFP.  */
+            if (disas_vfp_insn(env, s, insn)) {
+                goto illegal_op;
+            }
+            return;
+        }
         if (((insn & 0x0f30f000) == 0x0510f000) ||
             ((insn & 0x0f30f010) == 0x0710f000)) {
             if ((insn & (1 << 22)) == 0) {
@@ -8033,9 +8045,15 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
         case 0xc:
         case 0xd:
         case 0xe:
-            /* Coprocessor.  */
-            if (disas_coproc_insn(env, s, insn))
+            if (((insn >> 8) & 0xe) == 10) {
+                /* VFP.  */
+                if (disas_vfp_insn(env, s, insn)) {
+                    goto illegal_op;
+                }
+            } else if (disas_coproc_insn(env, s, insn)) {
+                /* Coprocessor.  */
                 goto illegal_op;
+            }
             break;
         case 0xf:
             /* swi */
@@ -8765,6 +8783,10 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
             insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
             if (disas_neon_data_insn(env, s, insn))
                 goto illegal_op;
+        } else if (((insn >> 8) & 0xe) == 10) {
+            if (disas_vfp_insn(env, s, insn)) {
+                goto illegal_op;
+            }
         } else {
             if (insn & (1 << 28))
                 goto illegal_op;
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PATCH v8 2/6] target-arm: Implement ARMv8 VSEL instruction.
  2013-12-04 11:54 [Qemu-devel] [PATCH v8 0/6] target-arm: Add support for VSEL and VMIN/MAXNM Will Newton
  2013-12-04 11:54 ` [Qemu-devel] [PATCH v8 1/6] target-arm: Move call to disas_vfp_insn out of disas_coproc_insn Will Newton
@ 2013-12-04 11:54 ` Will Newton
  2013-12-04 11:54 ` [Qemu-devel] [PATCH v8 3/6] softfloat: Remove unused argument from MINMAX macro Will Newton
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Will Newton @ 2013-12-04 11:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: patches

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

Signed-off-by: Will Newton <will.newton@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/translate.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 134 insertions(+), 1 deletion(-)

diff --git a/target-arm/translate.c b/target-arm/translate.c
index f63e89d..0a22ad8 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -2614,6 +2614,139 @@ static TCGv_i32 gen_load_and_replicate(DisasContext *s, TCGv_i32 addr, int size)
     return tmp;
 }
 
+static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
+                       uint32_t dp)
+{
+    uint32_t cc = extract32(insn, 20, 2);
+
+    if (dp) {
+        TCGv_i64 frn, frm, dest;
+        TCGv_i64 tmp, zero, zf, nf, vf;
+
+        zero = tcg_const_i64(0);
+
+        frn = tcg_temp_new_i64();
+        frm = tcg_temp_new_i64();
+        dest = 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_ext_i32_i64(nf, cpu_NF);
+        tcg_gen_ext_i32_i64(vf, cpu_VF);
+
+        tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
+        tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
+        switch (cc) {
+        case 0: /* eq: Z */
+            tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
+                                frn, frm);
+            break;
+        case 1: /* vs: V */
+            tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero,
+                                frn, frm);
+            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, dest, tmp, zero,
+                                frn, frm);
+            tcg_temp_free_i64(tmp);
+            break;
+        case 3: /* gt: !Z && N == V */
+            tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero,
+                                frn, frm);
+            tmp = tcg_temp_new_i64();
+            tcg_gen_xor_i64(tmp, vf, nf);
+            tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
+                                dest, frm);
+            tcg_temp_free_i64(tmp);
+            break;
+        }
+        tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
+        tcg_temp_free_i64(frn);
+        tcg_temp_free_i64(frm);
+        tcg_temp_free_i64(dest);
+
+        tcg_temp_free_i64(zf);
+        tcg_temp_free_i64(nf);
+        tcg_temp_free_i64(vf);
+
+        tcg_temp_free_i64(zero);
+    } else {
+        TCGv_i32 frn, frm, dest;
+        TCGv_i32 tmp, zero;
+
+        zero = tcg_const_i32(0);
+
+        frn = tcg_temp_new_i32();
+        frm = tcg_temp_new_i32();
+        dest = tcg_temp_new_i32();
+        tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
+        tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
+        switch (cc) {
+        case 0: /* eq: Z */
+            tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
+                                frn, frm);
+            break;
+        case 1: /* vs: V */
+            tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero,
+                                frn, frm);
+            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, dest, tmp, zero,
+                                frn, frm);
+            tcg_temp_free_i32(tmp);
+            break;
+        case 3: /* gt: !Z && N == V */
+            tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero,
+                                frn, frm);
+            tmp = tcg_temp_new_i32();
+            tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
+            tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
+                                dest, frm);
+            tcg_temp_free_i32(tmp);
+            break;
+        }
+        tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
+        tcg_temp_free_i32(frn);
+        tcg_temp_free_i32(frm);
+        tcg_temp_free_i32(dest);
+
+        tcg_temp_free_i32(zero);
+    }
+
+    return 0;
+}
+
+static int disas_vfp_v8_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
+{
+    uint32_t rd, rn, rm, dp = extract32(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) {
+        return handle_vsel(insn, rd, rn, rm, dp);
+    }
+    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)
@@ -2641,7 +2774,7 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
         /* 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] 8+ messages in thread

* [Qemu-devel] [PATCH v8 3/6] softfloat: Remove unused argument from MINMAX macro.
  2013-12-04 11:54 [Qemu-devel] [PATCH v8 0/6] target-arm: Add support for VSEL and VMIN/MAXNM Will Newton
  2013-12-04 11:54 ` [Qemu-devel] [PATCH v8 1/6] target-arm: Move call to disas_vfp_insn out of disas_coproc_insn Will Newton
  2013-12-04 11:54 ` [Qemu-devel] [PATCH v8 2/6] target-arm: Implement ARMv8 VSEL instruction Will Newton
@ 2013-12-04 11:54 ` Will Newton
  2013-12-04 11:54 ` [Qemu-devel] [PATCH v8 4/6] softfloat: Add minNum() and maxNum() functions to softfloat Will Newton
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Will Newton @ 2013-12-04 11:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: patches

The nan_exp argument is not used, so remove it.

Signed-off-by: Will Newton <will.newton@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
 fpu/softfloat.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 7ba51b6..97bf627 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -6706,7 +6706,7 @@ int float128_compare_quiet( float128 a, float128 b STATUS_PARAM )
  * 'compare and pick one input' because that would mishandle
  * NaNs and +0 vs -0.
  */
-#define MINMAX(s, nan_exp)                                              \
+#define MINMAX(s)                                                       \
 INLINE float ## s float ## s ## _minmax(float ## s a, float ## s b,     \
                                         int ismin STATUS_PARAM )        \
 {                                                                       \
@@ -6747,8 +6747,8 @@ float ## s float ## s ## _max(float ## s a, float ## s b STATUS_PARAM)  \
     return float ## s ## _minmax(a, b, 0 STATUS_VAR);                   \
 }
 
-MINMAX(32, 0xff)
-MINMAX(64, 0x7ff)
+MINMAX(32)
+MINMAX(64)
 
 
 /* Multiply A by 2 raised to the power N.  */
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PATCH v8 4/6] softfloat: Add minNum() and maxNum() functions to softfloat.
  2013-12-04 11:54 [Qemu-devel] [PATCH v8 0/6] target-arm: Add support for VSEL and VMIN/MAXNM Will Newton
                   ` (2 preceding siblings ...)
  2013-12-04 11:54 ` [Qemu-devel] [PATCH v8 3/6] softfloat: Remove unused argument from MINMAX macro Will Newton
@ 2013-12-04 11:54 ` Will Newton
  2013-12-04 11:54 ` [Qemu-devel] [PATCH v8 5/6] target-arm: Implement ARMv8 FP VMAXNM and VMINNM instructions Will Newton
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Will Newton @ 2013-12-04 11:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: patches

Add floatnn_minnum() and floatnn_maxnum() functions which are equivalent
to the minNum() and maxNum() functions from IEEE 754-2008. They are
similar to min() and max() but differ in the handling of QNaN arguments.

Signed-off-by: Will Newton <will.newton@linaro.org>
---
 fpu/softfloat.c         | 32 +++++++++++++++++++++++++++++---
 include/fpu/softfloat.h |  4 ++++
 2 files changed, 33 insertions(+), 3 deletions(-)

Changes in v8:
 - Use existing MINMAX macro to implement minnum and maxnum
 - Improve comment

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 97bf627..dbda61b 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -6705,10 +6705,17 @@ int float128_compare_quiet( float128 a, float128 b STATUS_PARAM )
 /* min() and max() functions. These can't be implemented as
  * 'compare and pick one input' because that would mishandle
  * NaNs and +0 vs -0.
+ *
+ * minnum() and maxnum() functions. These are similar to the min()
+ * and max() functions but if one of the arguments is a QNaN and
+ * the other is numerical then the numerical argument is returned.
+ * minnum() and maxnum correspond to the IEEE 754-2008 minNum()
+ * and maxNum() operations. min() and max() are the typical min/max
+ * semantics provided by many CPUs which predate that specification.
  */
 #define MINMAX(s)                                                       \
 INLINE float ## s float ## s ## _minmax(float ## s a, float ## s b,     \
-                                        int ismin STATUS_PARAM )        \
+                                        int ismin, int isieee STATUS_PARAM) \
 {                                                                       \
     flag aSign, bSign;                                                  \
     uint ## s ## _t av, bv;                                             \
@@ -6716,6 +6723,15 @@ INLINE float ## s float ## s ## _minmax(float ## s a, float ## s b,     \
     b = float ## s ## _squash_input_denormal(b STATUS_VAR);             \
     if (float ## s ## _is_any_nan(a) ||                                 \
         float ## s ## _is_any_nan(b)) {                                 \
+        if (isieee) {                                                   \
+            if (float ## s ## _is_quiet_nan(a) &&                       \
+                !float ## s ##_is_any_nan(b)) {                         \
+                return b;                                               \
+            } else if (float ## s ## _is_quiet_nan(b) &&                \
+                       !float ## s ## _is_any_nan(a)) {                 \
+                return a;                                               \
+            }                                                           \
+        }                                                               \
         return propagateFloat ## s ## NaN(a, b STATUS_VAR);             \
     }                                                                   \
     aSign = extractFloat ## s ## Sign(a);                               \
@@ -6739,12 +6755,22 @@ INLINE float ## s float ## s ## _minmax(float ## s a, float ## s b,     \
                                                                         \
 float ## s float ## s ## _min(float ## s a, float ## s b STATUS_PARAM)  \
 {                                                                       \
-    return float ## s ## _minmax(a, b, 1 STATUS_VAR);                   \
+    return float ## s ## _minmax(a, b, 1, 0 STATUS_VAR);                \
 }                                                                       \
                                                                         \
 float ## s float ## s ## _max(float ## s a, float ## s b STATUS_PARAM)  \
 {                                                                       \
-    return float ## s ## _minmax(a, b, 0 STATUS_VAR);                   \
+    return float ## s ## _minmax(a, b, 0, 0 STATUS_VAR);                \
+}                                                                       \
+                                                                        \
+float ## s float ## s ## _minnum(float ## s a, float ## s b STATUS_PARAM) \
+{                                                                       \
+    return float ## s ## _minmax(a, b, 1, 1 STATUS_VAR);                \
+}                                                                       \
+                                                                        \
+float ## s float ## s ## _maxnum(float ## s a, float ## s b STATUS_PARAM) \
+{                                                                       \
+    return float ## s ## _minmax(a, b, 0, 1 STATUS_VAR);                \
 }
 
 MINMAX(32)
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index f3927e2..2365274 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -302,6 +302,8 @@ int float32_compare( float32, float32 STATUS_PARAM );
 int float32_compare_quiet( float32, float32 STATUS_PARAM );
 float32 float32_min(float32, float32 STATUS_PARAM);
 float32 float32_max(float32, float32 STATUS_PARAM);
+float32 float32_minnum(float32, float32 STATUS_PARAM);
+float32 float32_maxnum(float32, float32 STATUS_PARAM);
 int float32_is_quiet_nan( float32 );
 int float32_is_signaling_nan( float32 );
 float32 float32_maybe_silence_nan( float32 );
@@ -408,6 +410,8 @@ int float64_compare( float64, float64 STATUS_PARAM );
 int float64_compare_quiet( float64, float64 STATUS_PARAM );
 float64 float64_min(float64, float64 STATUS_PARAM);
 float64 float64_max(float64, float64 STATUS_PARAM);
+float64 float64_minnum(float64, float64 STATUS_PARAM);
+float64 float64_maxnum(float64, float64 STATUS_PARAM);
 int float64_is_quiet_nan( float64 a );
 int float64_is_signaling_nan( float64 );
 float64 float64_maybe_silence_nan( float64 );
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PATCH v8 5/6] target-arm: Implement ARMv8 FP VMAXNM and VMINNM instructions.
  2013-12-04 11:54 [Qemu-devel] [PATCH v8 0/6] target-arm: Add support for VSEL and VMIN/MAXNM Will Newton
                   ` (3 preceding siblings ...)
  2013-12-04 11:54 ` [Qemu-devel] [PATCH v8 4/6] softfloat: Add minNum() and maxNum() functions to softfloat Will Newton
@ 2013-12-04 11:54 ` Will Newton
  2013-12-04 11:54 ` [Qemu-devel] [PATCH v8 6/6] target-arm: Implement ARMv8 SIMD " Will Newton
  2013-12-06 17:05 ` [Qemu-devel] [PATCH v8 0/6] target-arm: Add support for VSEL and VMIN/MAXNM Peter Maydell
  6 siblings, 0 replies; 8+ messages in thread
From: Will Newton @ 2013-12-04 11:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: patches

This adds support for the ARMv8 floating point VMAXNM and VMINNM
instructions.

Signed-off-by: Will Newton <will.newton@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/helper.c    | 25 +++++++++++++++++++++++++
 target-arm/helper.h    |  5 +++++
 target-arm/translate.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 80 insertions(+)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 3445813..7507240 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -4079,3 +4079,28 @@ float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c, void *fpstp)
     float_status *fpst = fpstp;
     return float64_muladd(a, b, c, 0, fpst);
 }
+
+/* ARMv8 VMAXNM/VMINNM */
+float32 VFP_HELPER(maxnm, s)(float32 a, float32 b, void *fpstp)
+{
+    float_status *fpst = fpstp;
+    return float32_maxnum(a, b, fpst);
+}
+
+float64 VFP_HELPER(maxnm, d)(float64 a, float64 b, void *fpstp)
+{
+    float_status *fpst = fpstp;
+    return float64_maxnum(a, b, fpst);
+}
+
+float32 VFP_HELPER(minnm, s)(float32 a, float32 b, void *fpstp)
+{
+    float_status *fpst = fpstp;
+    return float32_minnum(a, b, fpst);
+}
+
+float64 VFP_HELPER(minnm, d)(float64 a, float64 b, void *fpstp)
+{
+    float_status *fpst = fpstp;
+    return float64_minnum(a, b, fpst);
+}
diff --git a/target-arm/helper.h b/target-arm/helper.h
index cac9564..d459a39 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -132,6 +132,11 @@ DEF_HELPER_2(neon_fcvt_f32_to_f16, i32, f32, env)
 DEF_HELPER_4(vfp_muladdd, f64, f64, f64, f64, ptr)
 DEF_HELPER_4(vfp_muladds, f32, f32, f32, f32, ptr)
 
+DEF_HELPER_3(vfp_maxnmd, f64, f64, f64, ptr)
+DEF_HELPER_3(vfp_maxnms, f32, f32, f32, ptr)
+DEF_HELPER_3(vfp_minnmd, f64, f64, f64, ptr)
+DEF_HELPER_3(vfp_minnms, f32, f32, f32, ptr)
+
 DEF_HELPER_3(recps_f32, f32, f32, f32, env)
 DEF_HELPER_3(rsqrts_f32, f32, f32, f32, env)
 DEF_HELPER_2(recpe_f32, f32, f32, env)
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 0a22ad8..9a8069e 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -2723,6 +2723,54 @@ static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
     return 0;
 }
 
+static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
+                            uint32_t rm, uint32_t dp)
+{
+    uint32_t vmin = extract32(insn, 6, 1);
+    TCGv_ptr fpst = get_fpstatus_ptr(0);
+
+    if (dp) {
+        TCGv_i64 frn, frm, dest;
+
+        frn = tcg_temp_new_i64();
+        frm = tcg_temp_new_i64();
+        dest = tcg_temp_new_i64();
+
+        tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
+        tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
+        if (vmin) {
+            gen_helper_vfp_minnmd(dest, frn, frm, fpst);
+        } else {
+            gen_helper_vfp_maxnmd(dest, frn, frm, fpst);
+        }
+        tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
+        tcg_temp_free_i64(frn);
+        tcg_temp_free_i64(frm);
+        tcg_temp_free_i64(dest);
+    } else {
+        TCGv_i32 frn, frm, dest;
+
+        frn = tcg_temp_new_i32();
+        frm = tcg_temp_new_i32();
+        dest = tcg_temp_new_i32();
+
+        tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
+        tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
+        if (vmin) {
+            gen_helper_vfp_minnms(dest, frn, frm, fpst);
+        } else {
+            gen_helper_vfp_maxnms(dest, frn, frm, fpst);
+        }
+        tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
+        tcg_temp_free_i32(frn);
+        tcg_temp_free_i32(frm);
+        tcg_temp_free_i32(dest);
+    }
+
+    tcg_temp_free_ptr(fpst);
+    return 0;
+}
+
 static int disas_vfp_v8_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
 {
     uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
@@ -2743,6 +2791,8 @@ static int disas_vfp_v8_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
 
     if ((insn & 0x0f800e50) == 0x0e000a00) {
         return handle_vsel(insn, rd, rn, rm, dp);
+    } else if ((insn & 0x0fb00e10) == 0x0e800a00) {
+        return handle_vminmaxnm(insn, rd, rn, rm, dp);
     }
     return 1;
 }
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PATCH v8 6/6] target-arm: Implement ARMv8 SIMD VMAXNM and VMINNM instructions.
  2013-12-04 11:54 [Qemu-devel] [PATCH v8 0/6] target-arm: Add support for VSEL and VMIN/MAXNM Will Newton
                   ` (4 preceding siblings ...)
  2013-12-04 11:54 ` [Qemu-devel] [PATCH v8 5/6] target-arm: Implement ARMv8 FP VMAXNM and VMINNM instructions Will Newton
@ 2013-12-04 11:54 ` Will Newton
  2013-12-06 17:05 ` [Qemu-devel] [PATCH v8 0/6] target-arm: Add support for VSEL and VMIN/MAXNM Peter Maydell
  6 siblings, 0 replies; 8+ messages in thread
From: Will Newton @ 2013-12-04 11:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: patches

This adds support for the ARMv8 Advanced SIMD VMAXNM and VMINNM
instructions.

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

Changes in v8:
 - Use VFP helper instead of adding a NEON specific one
 - Drop size check

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 9a8069e..73ed266 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4553,7 +4553,7 @@ static void gen_neon_narrow_op(int op, int u, int size,
 #define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
 #define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
 #define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
-#define NEON_3R_VRECPS_VRSQRTS 31 /* float VRECPS, VRSQRTS */
+#define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
 
 static const uint8_t neon_3r_sizes[] = {
     [NEON_3R_VHADD] = 0x7,
@@ -4586,7 +4586,7 @@ static const uint8_t neon_3r_sizes[] = {
     [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
     [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
     [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
-    [NEON_3R_VRECPS_VRSQRTS] = 0x5, /* size bit 1 encodes op */
+    [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
 };
 
 /* Symbolic constants for op fields for Neon 2-register miscellaneous.
@@ -4847,8 +4847,9 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
                 return 1;
             }
             break;
-        case NEON_3R_VRECPS_VRSQRTS:
-            if (u) {
+        case NEON_3R_FLOAT_MISC:
+            /* VMAXNM/VMINNM in ARMv8 */
+            if (u && !arm_feature(env, ARM_FEATURE_V8)) {
                 return 1;
             }
             break;
@@ -5137,11 +5138,23 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
             tcg_temp_free_ptr(fpstatus);
             break;
         }
-        case NEON_3R_VRECPS_VRSQRTS:
-            if (size == 0)
-                gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
-            else
-                gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
+        case NEON_3R_FLOAT_MISC:
+            if (u) {
+                /* VMAXNM/VMINNM */
+                TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+                if (size == 0) {
+                    gen_helper_vfp_maxnms(tmp, tmp, tmp2, fpstatus);
+                } else {
+                    gen_helper_vfp_minnms(tmp, tmp, tmp2, fpstatus);
+                }
+                tcg_temp_free_ptr(fpstatus);
+            } else {
+                if (size == 0) {
+                    gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
+                } else {
+                    gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
+              }
+            }
             break;
         case NEON_3R_VFM:
         {
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] [PATCH v8 0/6] target-arm: Add support for VSEL and VMIN/MAXNM.
  2013-12-04 11:54 [Qemu-devel] [PATCH v8 0/6] target-arm: Add support for VSEL and VMIN/MAXNM Will Newton
                   ` (5 preceding siblings ...)
  2013-12-04 11:54 ` [Qemu-devel] [PATCH v8 6/6] target-arm: Implement ARMv8 SIMD " Will Newton
@ 2013-12-06 17:05 ` Peter Maydell
  6 siblings, 0 replies; 8+ messages in thread
From: Peter Maydell @ 2013-12-06 17:05 UTC (permalink / raw)
  To: Will Newton; +Cc: QEMU Developers, Patch Tracking

On 4 December 2013 11:54, Will Newton <will.newton@linaro.org> wrote:
> This series adds support for three new instructions added in ARMv8 -
> VSEL, VMINNM and VMAXNM.
>
> Will Newton (6):
>   target-arm: Move call to disas_vfp_insn out of disas_coproc_insn.
>   target-arm: Implement ARMv8 VSEL instruction.
>   softfloat: Remove unused argument from MINMAX macro.
>   softfloat: Add minNum() and maxNum() functions to softfloat.
>   target-arm: Implement ARMv8 FP VMAXNM and VMINNM instructions.
>   target-arm: Implement ARMv8 SIMD VMAXNM and VMINNM instructions.

Thanks. These patches all pass my random instruction tests and
look good. All patches
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
and added to target-arm.next.

NB: since these are all Linaro copyright changes, the softfloat
patches are provided under either the softfloat 2a or 2b license.

[we're currently halfway through attempting a relicense on
the softfloat code, hence the necessity for that remark.]

-- PMM

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2013-12-06 17:05 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-04 11:54 [Qemu-devel] [PATCH v8 0/6] target-arm: Add support for VSEL and VMIN/MAXNM Will Newton
2013-12-04 11:54 ` [Qemu-devel] [PATCH v8 1/6] target-arm: Move call to disas_vfp_insn out of disas_coproc_insn Will Newton
2013-12-04 11:54 ` [Qemu-devel] [PATCH v8 2/6] target-arm: Implement ARMv8 VSEL instruction Will Newton
2013-12-04 11:54 ` [Qemu-devel] [PATCH v8 3/6] softfloat: Remove unused argument from MINMAX macro Will Newton
2013-12-04 11:54 ` [Qemu-devel] [PATCH v8 4/6] softfloat: Add minNum() and maxNum() functions to softfloat Will Newton
2013-12-04 11:54 ` [Qemu-devel] [PATCH v8 5/6] target-arm: Implement ARMv8 FP VMAXNM and VMINNM instructions Will Newton
2013-12-04 11:54 ` [Qemu-devel] [PATCH v8 6/6] target-arm: Implement ARMv8 SIMD " Will Newton
2013-12-06 17:05 ` [Qemu-devel] [PATCH v8 0/6] target-arm: Add support for VSEL and VMIN/MAXNM Peter Maydell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).