* [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).