qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH V2 00/10] ARM: fix VCVT instructions
@ 2010-12-06 17:00 Peter Maydell
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 01/10] ARM: Fix decoding of VFP forms of VCVT between float and int/fixed Peter Maydell
                   ` (9 more replies)
  0 siblings, 10 replies; 15+ messages in thread
From: Peter Maydell @ 2010-12-06 17:00 UTC (permalink / raw)
  To: qemu-devel

This patch series corrects a number of errors in the decoding and
implementation of various forms of the ARM VCVT instruction. The
resulting qemu has been tested by execution of 100,000 random
variants of these instruction patterns with register values
cross-checked against the results given by Cortex-A8 hardware.

Thanks to Johan Bengtsson for posting the initial VCVT related
patch which prompted me to do some more testing in this area.

This is V2 of this patchset which addresses Nathan Froyd's
suggestion that we should be doing all the bit-twiddling
in softfloat rather than in the ARM specific files. The
old patch 4/8 is now 4/10 and 5/10, and the old 5/8 is
now 6/10 and 7/10; all other patches are unchanged.

In patch 4/10 I've left the '_any_' in the function name to
avoid a clash/dependency on the proposed 'rename _is_nan to
_is_quiet_nan' patch.


Peter Maydell (10):
  ARM: Fix decoding of VFP forms of VCVT between float and int/fixed
  ARM: Fix decoding of Neon forms of VCVT between float and fixed point
  ARM: Fix sense of to_integer bit in Neon VCVT float/int conversion
  softfloat: Add float*_is_any_nan() functions
  ARM: Return correct result for float-to-integer conversion of NaN
  softfloat: Add float*_maybe_silence_nan() functions
  ARM: Return correct result for single<->double conversion of NaN
  ARM: Ignore top 16 bits when doing VCVT from 16 bit fixed point
  softfloat: Add float/double to 16 bit integer conversion functions
  ARM: Implement VCVT to 16 bit integer using new softfloat routines

 fpu/softfloat-specialize.h |   38 ++++++++++++
 fpu/softfloat.c            |  136 ++++++++++++++++++++++++++++++++++++++++++++
 fpu/softfloat.h            |   16 +++++
 target-arm/helper.c        |   43 +++++++++++++-
 target-arm/translate.c     |   35 +++++++----
 5 files changed, 251 insertions(+), 17 deletions(-)

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

* [Qemu-devel] [PATCH 01/10] ARM: Fix decoding of VFP forms of VCVT between float and int/fixed
  2010-12-06 17:00 [Qemu-devel] [PATCH V2 00/10] ARM: fix VCVT instructions Peter Maydell
@ 2010-12-06 17:00 ` Peter Maydell
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 02/10] ARM: Fix decoding of Neon forms of VCVT between float and fixed point Peter Maydell
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: Peter Maydell @ 2010-12-06 17:00 UTC (permalink / raw)
  To: qemu-devel

Correct the decoding of source and destination registers
for the VFP forms of the VCVT instructions which convert
between floating point and integer or fixed-point.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Nathan Froyd <froydnj@codesourcery.com>
---
 target-arm/translate.c |   19 ++++++++++++-------
 1 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 99464ab..0c8439a 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -2870,16 +2870,18 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     VFP_DREG_N(rn, insn);
                 }
 
-                if (op == 15 && (rn == 15 || rn > 17)) {
+                if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18))) {
                     /* Integer or single precision destination.  */
                     rd = VFP_SREG_D(insn);
                 } else {
                     VFP_DREG_D(rd, insn);
                 }
-
-                if (op == 15 && (rn == 16 || rn == 17)) {
-                    /* Integer source.  */
-                    rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
+                if (op == 15 && 
+                    (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14))) {
+                    /* VCVT from int is always from S reg regardless of dp bit.
+                     * VCVT with immediate frac_bits has same format as SREG_M
+                     */
+                    rm = VFP_SREG_M(insn);
                 } else {
                     VFP_DREG_M(rm, insn);
                 }
@@ -2891,6 +2893,9 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 } else {
                     rd = VFP_SREG_D(insn);
                 }
+                /* NB that we implicitly rely on the encoding for the frac_bits
+                 * in VCVT of fixed to float being the same as that of an SREG_M.
+                 */
                 rm = VFP_SREG_M(insn);
             }
 
@@ -3179,8 +3184,8 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 /* Write back the result.  */
                 if (op == 15 && (rn >= 8 && rn <= 11))
                     ; /* Comparison, do nothing.  */
-                else if (op == 15 && rn > 17)
-                    /* Integer result.  */
+                else if (op == 15 && dp && ((rn & 0x1c) == 0x18))
+                    /* VCVT double to int: always integer result. */
                     gen_mov_vreg_F0(0, rd);
                 else if (op == 15 && rn == 15)
                     /* conversion */
-- 
1.6.3.3

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

* [Qemu-devel] [PATCH 02/10] ARM: Fix decoding of Neon forms of VCVT between float and fixed point
  2010-12-06 17:00 [Qemu-devel] [PATCH V2 00/10] ARM: fix VCVT instructions Peter Maydell
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 01/10] ARM: Fix decoding of VFP forms of VCVT between float and int/fixed Peter Maydell
@ 2010-12-06 17:00 ` Peter Maydell
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 03/10] ARM: Fix sense of to_integer bit in Neon VCVT float/int conversion Peter Maydell
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: Peter Maydell @ 2010-12-06 17:00 UTC (permalink / raw)
  To: qemu-devel

Fix errors in the decoding of the Neon forms of fixed-point VCVT:
 * fixed-point VCVT is op 14 and 15, not 15 and 16
 * the fbits immediate field was being misinterpreted
 * the sense of the to_fixed bit was inverted

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Nathan Froyd <froydnj@codesourcery.com>
---
 target-arm/translate.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 0c8439a..696abf6 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4850,11 +4850,15 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     }
                     neon_store_reg64(cpu_V0, rd + pass);
                 }
-            } else if (op == 15 || op == 16) {
+            } else if (op >= 14) {
                 /* VCVT fixed-point.  */
+                /* We have already masked out the must-be-1 top bit of imm6,
+                 * hence this 32-shift where the ARM ARM has 64-imm6.
+                 */
+                shift = 32 - shift;
                 for (pass = 0; pass < (q ? 4 : 2); pass++) {
                     tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
-                    if (op & 1) {
+                    if (!(op & 1)) {
                         if (u)
                             gen_vfp_ulto(0, shift);
                         else
-- 
1.6.3.3

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

* [Qemu-devel] [PATCH 03/10] ARM: Fix sense of to_integer bit in Neon VCVT float/int conversion
  2010-12-06 17:00 [Qemu-devel] [PATCH V2 00/10] ARM: fix VCVT instructions Peter Maydell
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 01/10] ARM: Fix decoding of VFP forms of VCVT between float and int/fixed Peter Maydell
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 02/10] ARM: Fix decoding of Neon forms of VCVT between float and fixed point Peter Maydell
@ 2010-12-06 17:00 ` Peter Maydell
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 04/10] softfloat: Add float*_is_any_nan() functions Peter Maydell
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: Peter Maydell @ 2010-12-06 17:00 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Nathan Froyd <froydnj@codesourcery.com>
---
 target-arm/translate.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 696abf6..afb3872 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -5664,16 +5664,16 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
                             break;
                         case 60: /* VCVT.F32.S32 */
-                            gen_vfp_tosiz(0);
+                            gen_vfp_sito(0);
                             break;
                         case 61: /* VCVT.F32.U32 */
-                            gen_vfp_touiz(0);
+                            gen_vfp_uito(0);
                             break;
                         case 62: /* VCVT.S32.F32 */
-                            gen_vfp_sito(0);
+                            gen_vfp_tosiz(0);
                             break;
                         case 63: /* VCVT.U32.F32 */
-                            gen_vfp_uito(0);
+                            gen_vfp_touiz(0);
                             break;
                         default:
                             /* Reserved: 21, 29, 39-56 */
-- 
1.6.3.3

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

* [Qemu-devel] [PATCH 04/10] softfloat: Add float*_is_any_nan() functions
  2010-12-06 17:00 [Qemu-devel] [PATCH V2 00/10] ARM: fix VCVT instructions Peter Maydell
                   ` (2 preceding siblings ...)
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 03/10] ARM: Fix sense of to_integer bit in Neon VCVT float/int conversion Peter Maydell
@ 2010-12-06 17:00 ` Peter Maydell
  2010-12-06 18:15   ` Nathan Froyd
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 05/10] ARM: Return correct result for float-to-integer conversion of NaN Peter Maydell
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 15+ messages in thread
From: Peter Maydell @ 2010-12-06 17:00 UTC (permalink / raw)
  To: qemu-devel

Add float*_is_any_nan() functions which return true if the argument
is a NaN of any kind (quiet or signalling).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 fpu/softfloat.h |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index 9528825..9bece80 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -314,6 +314,11 @@ INLINE int float32_is_zero(float32 a)
     return (float32_val(a) & 0x7fffffff) == 0;
 }
 
+INLINE int float32_is_any_nan(float32 a)
+{
+    return ((float32_val(a) & ~(1 << 31)) > 0x7f800000UL);
+}
+
 #define float32_zero make_float32(0)
 #define float32_one make_float32(0x3f800000)
 #define float32_ln2 make_float32(0x3f317218)
@@ -386,6 +391,11 @@ INLINE int float64_is_zero(float64 a)
     return (float64_val(a) & 0x7fffffffffffffffLL) == 0;
 }
 
+INLINE int float64_is_any_nan(float64 a)
+{
+    return ((float64_val(a) & ~(1ULL << 63)) > 0x7ff0000000000000ULL);
+}
+
 #define float64_zero make_float64(0)
 #define float64_one make_float64(0x3ff0000000000000LL)
 #define float64_ln2 make_float64(0x3fe62e42fefa39efLL)
-- 
1.6.3.3

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

* [Qemu-devel] [PATCH 05/10] ARM: Return correct result for float-to-integer conversion of NaN
  2010-12-06 17:00 [Qemu-devel] [PATCH V2 00/10] ARM: fix VCVT instructions Peter Maydell
                   ` (3 preceding siblings ...)
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 04/10] softfloat: Add float*_is_any_nan() functions Peter Maydell
@ 2010-12-06 17:00 ` Peter Maydell
  2010-12-06 18:18   ` Nathan Froyd
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 06/10] softfloat: Add float*_maybe_silence_nan() functions Peter Maydell
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 15+ messages in thread
From: Peter Maydell @ 2010-12-06 17:00 UTC (permalink / raw)
  To: qemu-devel

The ARM architecture mandates that converting a NaN value to
integer gives zero (if Invalid Operation FP exceptions are
not being trapped). This isn't the behaviour of the SoftFloat
library, so NaNs must be special-cased.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/helper.c |   27 +++++++++++++++++++++++++++
 1 files changed, 27 insertions(+), 0 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 2a1f448..6d2a8f2 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2463,41 +2463,65 @@ float64 VFP_HELPER(sito, d)(float32 x, CPUState *env)
 /* Float to integer conversion.  */
 float32 VFP_HELPER(toui, s)(float32 x, CPUState *env)
 {
+    if (float32_is_any_nan(x)) {
+        return float32_zero;
+    }
     return vfp_itos(float32_to_uint32(x, &env->vfp.fp_status));
 }
 
 float32 VFP_HELPER(toui, d)(float64 x, CPUState *env)
 {
+    if (float64_is_any_nan(x)) {
+        return float32_zero;
+    }
     return vfp_itos(float64_to_uint32(x, &env->vfp.fp_status));
 }
 
 float32 VFP_HELPER(tosi, s)(float32 x, CPUState *env)
 {
+    if (float32_is_any_nan(x)) {
+        return float32_zero;
+    }
     return vfp_itos(float32_to_int32(x, &env->vfp.fp_status));
 }
 
 float32 VFP_HELPER(tosi, d)(float64 x, CPUState *env)
 {
+    if (float64_is_any_nan(x)) {
+        return float32_zero;
+    }
     return vfp_itos(float64_to_int32(x, &env->vfp.fp_status));
 }
 
 float32 VFP_HELPER(touiz, s)(float32 x, CPUState *env)
 {
+    if (float32_is_any_nan(x)) {
+        return float32_zero;
+    }
     return vfp_itos(float32_to_uint32_round_to_zero(x, &env->vfp.fp_status));
 }
 
 float32 VFP_HELPER(touiz, d)(float64 x, CPUState *env)
 {
+    if (float64_is_any_nan(x)) {
+        return float32_zero;
+    }
     return vfp_itos(float64_to_uint32_round_to_zero(x, &env->vfp.fp_status));
 }
 
 float32 VFP_HELPER(tosiz, s)(float32 x, CPUState *env)
 {
+    if (float32_is_any_nan(x)) {
+        return float32_zero;
+    }
     return vfp_itos(float32_to_int32_round_to_zero(x, &env->vfp.fp_status));
 }
 
 float32 VFP_HELPER(tosiz, d)(float64 x, CPUState *env)
 {
+    if (float64_is_any_nan(x)) {
+        return float32_zero;
+    }
     return vfp_itos(float64_to_int32_round_to_zero(x, &env->vfp.fp_status));
 }
 
@@ -2524,6 +2548,9 @@ ftype VFP_HELPER(name##to, p)(ftype x, uint32_t shift, CPUState *env) \
 ftype VFP_HELPER(to##name, p)(ftype x, uint32_t shift, CPUState *env) \
 { \
     ftype tmp; \
+    if (ftype##_is_any_nan(x)) { \
+        return ftype##_zero; \
+    } \
     tmp = ftype##_scalbn(x, shift, &env->vfp.fp_status); \
     return vfp_ito##p((itype)ftype##_to_##sign##int32_round_to_zero(tmp, \
         &env->vfp.fp_status)); \
-- 
1.6.3.3

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

* [Qemu-devel] [PATCH 06/10] softfloat: Add float*_maybe_silence_nan() functions
  2010-12-06 17:00 [Qemu-devel] [PATCH V2 00/10] ARM: fix VCVT instructions Peter Maydell
                   ` (4 preceding siblings ...)
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 05/10] ARM: Return correct result for float-to-integer conversion of NaN Peter Maydell
@ 2010-12-06 17:00 ` Peter Maydell
  2010-12-06 18:16   ` Nathan Froyd
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 07/10] ARM: Return correct result for single<->double conversion of NaN Peter Maydell
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 15+ messages in thread
From: Peter Maydell @ 2010-12-06 17:00 UTC (permalink / raw)
  To: qemu-devel

Add functions float*_maybe_silence_nan() which ensure that a
value is not a signaling NaN by turning it into a quiet NaN.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 fpu/softfloat-specialize.h |   38 ++++++++++++++++++++++++++++++++++++++
 fpu/softfloat.h            |    2 ++
 2 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 8e6aceb..0746878 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -102,6 +102,25 @@ int float32_is_signaling_nan( float32 a_ )
 }
 
 /*----------------------------------------------------------------------------
+| Returns a quiet NaN if the single-precision floating point value `a' is a
+| signaling NaN; otherwise returns `a'.
+*----------------------------------------------------------------------------*/
+
+float32 float32_maybe_silence_nan( float32 a_ )
+{
+    if (float32_is_signaling_nan(a_)) {
+        uint32_t a = float32_val(a_);
+#if SNAN_BIT_IS_ONE
+        a &= ~(1 << 22);
+#else
+        a |= (1 << 22);
+#endif
+        return make_float32(a);
+    }
+    return a_;
+}
+
+/*----------------------------------------------------------------------------
 | Returns the result of converting the single-precision floating-point NaN
 | `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
 | exception is raised.
@@ -234,6 +253,25 @@ int float64_is_signaling_nan( float64 a_ )
 }
 
 /*----------------------------------------------------------------------------
+| Returns a quiet NaN if the double-precision floating point value `a' is a
+| signaling NaN; otherwise returns `a'.
+*----------------------------------------------------------------------------*/
+
+float64 float64_maybe_silence_nan( float64 a_ )
+{
+    if (float64_is_signaling_nan(a_)) {
+        bits64 a = float64_val(a_);
+#if SNAN_BIT_IS_ONE
+        a &= ~LIT64( 0x0008000000000000 );
+#else
+        a |= LIT64( 0x0008000000000000 );
+#endif
+        return make_float64(a);
+    }
+    return a_;
+}
+
+/*----------------------------------------------------------------------------
 | Returns the result of converting the double-precision floating-point NaN
 | `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
 | exception is raised.
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index 9bece80..2e651e2 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -287,6 +287,7 @@ int float32_compare( float32, float32 STATUS_PARAM );
 int float32_compare_quiet( float32, float32 STATUS_PARAM );
 int float32_is_nan( float32 );
 int float32_is_signaling_nan( float32 );
+float32 float32_maybe_silence_nan( float32 );
 float32 float32_scalbn( float32, int STATUS_PARAM );
 
 INLINE float32 float32_abs(float32 a)
@@ -364,6 +365,7 @@ int float64_compare( float64, float64 STATUS_PARAM );
 int float64_compare_quiet( float64, float64 STATUS_PARAM );
 int float64_is_nan( float64 a );
 int float64_is_signaling_nan( float64 );
+float64 float64_maybe_silence_nan( float64 );
 float64 float64_scalbn( float64, int STATUS_PARAM );
 
 INLINE float64 float64_abs(float64 a)
-- 
1.6.3.3

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

* [Qemu-devel] [PATCH 07/10] ARM: Return correct result for single<->double conversion of NaN
  2010-12-06 17:00 [Qemu-devel] [PATCH V2 00/10] ARM: fix VCVT instructions Peter Maydell
                   ` (5 preceding siblings ...)
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 06/10] softfloat: Add float*_maybe_silence_nan() functions Peter Maydell
@ 2010-12-06 17:00 ` Peter Maydell
  2010-12-06 18:17   ` Nathan Froyd
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 08/10] ARM: Ignore top 16 bits when doing VCVT from 16 bit fixed point Peter Maydell
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 15+ messages in thread
From: Peter Maydell @ 2010-12-06 17:00 UTC (permalink / raw)
  To: qemu-devel

The ARM ARM defines that if the input to a single<->double conversion
is a NaN then the output is always forced to be a quiet NaN by setting
the most significant bit of the fraction part.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/helper.c |   12 ++++++++++--
 1 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 6d2a8f2..4bd1cd4 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2528,12 +2528,20 @@ float32 VFP_HELPER(tosiz, d)(float64 x, CPUState *env)
 /* floating point conversion */
 float64 VFP_HELPER(fcvtd, s)(float32 x, CPUState *env)
 {
-    return float32_to_float64(x, &env->vfp.fp_status);
+    float64 r = float32_to_float64(x, &env->vfp.fp_status);
+    /* ARM requires that S<->D conversion of any kind of NaN generates
+     * a quiet NaN by forcing the most significant frac bit to 1.
+     */
+    return float64_maybe_silence_nan(r);
 }
 
 float32 VFP_HELPER(fcvts, d)(float64 x, CPUState *env)
 {
-    return float64_to_float32(x, &env->vfp.fp_status);
+    float32 r =  float64_to_float32(x, &env->vfp.fp_status);
+    /* ARM requires that S<->D conversion of any kind of NaN generates
+     * a quiet NaN by forcing the most significant frac bit to 1.
+     */
+    return float32_maybe_silence_nan(r);
 }
 
 /* VFP3 fixed point conversion.  */
-- 
1.6.3.3

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

* [Qemu-devel] [PATCH 08/10] ARM: Ignore top 16 bits when doing VCVT from 16 bit fixed point
  2010-12-06 17:00 [Qemu-devel] [PATCH V2 00/10] ARM: fix VCVT instructions Peter Maydell
                   ` (6 preceding siblings ...)
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 07/10] ARM: Return correct result for single<->double conversion of NaN Peter Maydell
@ 2010-12-06 17:00 ` Peter Maydell
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 09/10] softfloat: Add float/double to 16 bit integer conversion functions Peter Maydell
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 10/10] ARM: Implement VCVT to 16 bit integer using new softfloat routines Peter Maydell
  9 siblings, 0 replies; 15+ messages in thread
From: Peter Maydell @ 2010-12-06 17:00 UTC (permalink / raw)
  To: qemu-devel

VCVT of 16 bit fixed point to float should ignore the top 16 bits
of the source register. Cast to int16_t and friends rather than
int16 -- the former is guaranteed exactly 16 bits wide where the
latter is merely at least 16 bits wide (and so is usually 32 bits).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Nathan Froyd <froydnj@codesourcery.com>
---
 target-arm/helper.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 4bd1cd4..2925782 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2549,7 +2549,7 @@ float32 VFP_HELPER(fcvts, d)(float64 x, CPUState *env)
 ftype VFP_HELPER(name##to, p)(ftype x, uint32_t shift, CPUState *env) \
 { \
     ftype tmp; \
-    tmp = sign##int32_to_##ftype ((itype)vfp_##p##toi(x), \
+    tmp = sign##int32_to_##ftype ((itype##_t)vfp_##p##toi(x), \
                                   &env->vfp.fp_status); \
     return ftype##_scalbn(tmp, -(int)shift, &env->vfp.fp_status); \
 } \
-- 
1.6.3.3

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

* [Qemu-devel] [PATCH 09/10] softfloat: Add float/double to 16 bit integer conversion functions
  2010-12-06 17:00 [Qemu-devel] [PATCH V2 00/10] ARM: fix VCVT instructions Peter Maydell
                   ` (7 preceding siblings ...)
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 08/10] ARM: Ignore top 16 bits when doing VCVT from 16 bit fixed point Peter Maydell
@ 2010-12-06 17:00 ` Peter Maydell
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 10/10] ARM: Implement VCVT to 16 bit integer using new softfloat routines Peter Maydell
  9 siblings, 0 replies; 15+ messages in thread
From: Peter Maydell @ 2010-12-06 17:00 UTC (permalink / raw)
  To: qemu-devel

The ARM architecture needs float/double to 16 bit integer conversions.
(The 32 bit versions aren't sufficient because of the requirement
to saturate at 16 bit MAXINT/MININT and to get the exception bits right.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Nathan Froyd <froydnj@codesourcery.com>
---
 fpu/softfloat.c |  136 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fpu/softfloat.h |    4 ++
 2 files changed, 140 insertions(+), 0 deletions(-)

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 0b82797..6f5b05d 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -1355,6 +1355,55 @@ int32 float32_to_int32_round_to_zero( float32 a STATUS_PARAM )
 
 /*----------------------------------------------------------------------------
 | Returns the result of converting the single-precision floating-point value
+| `a' to the 16-bit two's complement integer format.  The conversion is
+| performed according to the IEC/IEEE Standard for Binary Floating-Point
+| Arithmetic, except that the conversion is always rounded toward zero.
+| If `a' is a NaN, the largest positive integer is returned.  Otherwise, if
+| the conversion overflows, the largest integer with the same sign as `a' is
+| returned.
+*----------------------------------------------------------------------------*/
+
+int16 float32_to_int16_round_to_zero( float32 a STATUS_PARAM )
+{
+    flag aSign;
+    int16 aExp, shiftCount;
+    bits32 aSig;
+    int32 z;
+
+    aSig = extractFloat32Frac( a );
+    aExp = extractFloat32Exp( a );
+    aSign = extractFloat32Sign( a );
+    shiftCount = aExp - 0x8E;
+    if ( 0 <= shiftCount ) {
+        if ( float32_val(a) != 0xC7000000 ) {
+            float_raise( float_flag_invalid STATUS_VAR);
+            if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) {
+                return 0x7FFF;
+            }
+        }
+        return (sbits32) 0xffff8000;
+    }
+    else if ( aExp <= 0x7E ) {
+        if ( aExp | aSig ) {
+            STATUS(float_exception_flags) |= float_flag_inexact;
+        }
+        return 0;
+    }
+    shiftCount -= 0x10;
+    aSig = ( aSig | 0x00800000 )<<8;
+    z = aSig>>( - shiftCount );
+    if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) {
+        STATUS(float_exception_flags) |= float_flag_inexact;
+    }
+    if ( aSign ) {
+        z = - z;
+    }
+    return z;
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of converting the single-precision floating-point value
 | `a' to the 64-bit two's complement integer format.  The conversion is
 | performed according to the IEC/IEEE Standard for Binary Floating-Point
 | Arithmetic---which means in particular that the conversion is rounded
@@ -2412,6 +2461,57 @@ int32 float64_to_int32_round_to_zero( float64 a STATUS_PARAM )
 
 /*----------------------------------------------------------------------------
 | Returns the result of converting the double-precision floating-point value
+| `a' to the 16-bit two's complement integer format.  The conversion is
+| performed according to the IEC/IEEE Standard for Binary Floating-Point
+| Arithmetic, except that the conversion is always rounded toward zero.
+| If `a' is a NaN, the largest positive integer is returned.  Otherwise, if
+| the conversion overflows, the largest integer with the same sign as `a' is
+| returned.
+*----------------------------------------------------------------------------*/
+
+int16 float64_to_int16_round_to_zero( float64 a STATUS_PARAM )
+{
+    flag aSign;
+    int16 aExp, shiftCount;
+    bits64 aSig, savedASig;
+    int32 z;
+
+    aSig = extractFloat64Frac( a );
+    aExp = extractFloat64Exp( a );
+    aSign = extractFloat64Sign( a );
+    if ( 0x40E < aExp ) {
+        if ( ( aExp == 0x7FF ) && aSig ) {
+            aSign = 0;
+        }
+        goto invalid;
+    }
+    else if ( aExp < 0x3FF ) {
+        if ( aExp || aSig ) {
+            STATUS(float_exception_flags) |= float_flag_inexact;
+        }
+        return 0;
+    }
+    aSig |= LIT64( 0x0010000000000000 );
+    shiftCount = 0x433 - aExp;
+    savedASig = aSig;
+    aSig >>= shiftCount;
+    z = aSig;
+    if ( aSign ) {
+        z = - z;
+    }
+    if ( ( (int16_t)z < 0 ) ^ aSign ) {
+ invalid:
+        float_raise( float_flag_invalid STATUS_VAR);
+        return aSign ? (sbits32) 0xffff8000 : 0x7FFF;
+    }
+    if ( ( aSig<<shiftCount ) != savedASig ) {
+        STATUS(float_exception_flags) |= float_flag_inexact;
+    }
+    return z;
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of converting the double-precision floating-point value
 | `a' to the 64-bit two's complement integer format.  The conversion is
 | performed according to the IEC/IEEE Standard for Binary Floating-Point
 | Arithmetic---which means in particular that the conversion is rounded
@@ -5632,6 +5732,24 @@ unsigned int float32_to_uint32_round_to_zero( float32 a STATUS_PARAM )
     return res;
 }
 
+unsigned int float32_to_uint16_round_to_zero( float32 a STATUS_PARAM )
+{
+    int64_t v;
+    unsigned int res;
+
+    v = float32_to_int64_round_to_zero(a STATUS_VAR);
+    if (v < 0) {
+        res = 0;
+        float_raise( float_flag_invalid STATUS_VAR);
+    } else if (v > 0xffff) {
+        res = 0xffff;
+        float_raise( float_flag_invalid STATUS_VAR);
+    } else {
+        res = v;
+    }
+    return res;
+}
+
 unsigned int float64_to_uint32( float64 a STATUS_PARAM )
 {
     int64_t v;
@@ -5668,6 +5786,24 @@ unsigned int float64_to_uint32_round_to_zero( float64 a STATUS_PARAM )
     return res;
 }
 
+unsigned int float64_to_uint16_round_to_zero( float64 a STATUS_PARAM )
+{
+    int64_t v;
+    unsigned int res;
+
+    v = float64_to_int64_round_to_zero(a STATUS_VAR);
+    if (v < 0) {
+        res = 0;
+        float_raise( float_flag_invalid STATUS_VAR);
+    } else if (v > 0xffff) {
+        res = 0xffff;
+        float_raise( float_flag_invalid STATUS_VAR);
+    } else {
+        res = v;
+    }
+    return res;
+}
+
 /* FIXME: This looks broken.  */
 uint64_t float64_to_uint64 (float64 a STATUS_PARAM)
 {
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index 2e651e2..1c1004d 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -251,6 +251,8 @@ float32 float16_to_float32( bits16, flag STATUS_PARAM );
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE single-precision conversion routines.
 *----------------------------------------------------------------------------*/
+int float32_to_int16_round_to_zero( float32 STATUS_PARAM );
+unsigned int float32_to_uint16_round_to_zero( float32 STATUS_PARAM );
 int float32_to_int32( float32 STATUS_PARAM );
 int float32_to_int32_round_to_zero( float32 STATUS_PARAM );
 unsigned int float32_to_uint32( float32 STATUS_PARAM );
@@ -327,6 +329,8 @@ INLINE int float32_is_any_nan(float32 a)
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE double-precision conversion routines.
 *----------------------------------------------------------------------------*/
+int float64_to_int16_round_to_zero( float64 STATUS_PARAM );
+unsigned int float64_to_uint16_round_to_zero( float64 STATUS_PARAM );
 int float64_to_int32( float64 STATUS_PARAM );
 int float64_to_int32_round_to_zero( float64 STATUS_PARAM );
 unsigned int float64_to_uint32( float64 STATUS_PARAM );
-- 
1.6.3.3

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

* [Qemu-devel] [PATCH 10/10] ARM: Implement VCVT to 16 bit integer using new softfloat routines
  2010-12-06 17:00 [Qemu-devel] [PATCH V2 00/10] ARM: fix VCVT instructions Peter Maydell
                   ` (8 preceding siblings ...)
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 09/10] softfloat: Add float/double to 16 bit integer conversion functions Peter Maydell
@ 2010-12-06 17:00 ` Peter Maydell
  9 siblings, 0 replies; 15+ messages in thread
From: Peter Maydell @ 2010-12-06 17:00 UTC (permalink / raw)
  To: qemu-devel

Use the softfloat conversion routines for conversion to 16 bit
integers, because just casting to a 16 bit type truncates the
value rather than saturating it at 16-bit MAXINT/MININT.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Nathan Froyd <froydnj@codesourcery.com>
---
 target-arm/helper.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 2925782..9ba2f4f 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2560,7 +2560,7 @@ ftype VFP_HELPER(to##name, p)(ftype x, uint32_t shift, CPUState *env) \
         return ftype##_zero; \
     } \
     tmp = ftype##_scalbn(x, shift, &env->vfp.fp_status); \
-    return vfp_ito##p((itype)ftype##_to_##sign##int32_round_to_zero(tmp, \
+    return vfp_ito##p(ftype##_to_##itype##_round_to_zero(tmp, \
         &env->vfp.fp_status)); \
 }
 
-- 
1.6.3.3

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

* Re: [Qemu-devel] [PATCH 04/10] softfloat: Add float*_is_any_nan() functions
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 04/10] softfloat: Add float*_is_any_nan() functions Peter Maydell
@ 2010-12-06 18:15   ` Nathan Froyd
  0 siblings, 0 replies; 15+ messages in thread
From: Nathan Froyd @ 2010-12-06 18:15 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel

On Mon, Dec 06, 2010 at 05:00:05PM +0000, Peter Maydell wrote:
> Add float*_is_any_nan() functions which return true if the argument
> is a NaN of any kind (quiet or signalling).
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Nathan Froyd <froydnj@codesourcery.com>

-Nathan

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

* Re: [Qemu-devel] [PATCH 06/10] softfloat: Add float*_maybe_silence_nan() functions
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 06/10] softfloat: Add float*_maybe_silence_nan() functions Peter Maydell
@ 2010-12-06 18:16   ` Nathan Froyd
  0 siblings, 0 replies; 15+ messages in thread
From: Nathan Froyd @ 2010-12-06 18:16 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel

On Mon, Dec 06, 2010 at 05:00:07PM +0000, Peter Maydell wrote:
> Add functions float*_maybe_silence_nan() which ensure that a
> value is not a signaling NaN by turning it into a quiet NaN.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Nathan Froyd <froydnj@codesourcery.com>

-Nathan

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

* Re: [Qemu-devel] [PATCH 07/10] ARM: Return correct result for single<->double conversion of NaN
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 07/10] ARM: Return correct result for single<->double conversion of NaN Peter Maydell
@ 2010-12-06 18:17   ` Nathan Froyd
  0 siblings, 0 replies; 15+ messages in thread
From: Nathan Froyd @ 2010-12-06 18:17 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel

On Mon, Dec 06, 2010 at 05:00:08PM +0000, Peter Maydell wrote:
> The ARM ARM defines that if the input to a single<->double conversion
> is a NaN then the output is always forced to be a quiet NaN by setting
> the most significant bit of the fraction part.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Nathan Froyd <froydnj@codesourcery.com>

-Nathan

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

* Re: [Qemu-devel] [PATCH 05/10] ARM: Return correct result for float-to-integer conversion of NaN
  2010-12-06 17:00 ` [Qemu-devel] [PATCH 05/10] ARM: Return correct result for float-to-integer conversion of NaN Peter Maydell
@ 2010-12-06 18:18   ` Nathan Froyd
  0 siblings, 0 replies; 15+ messages in thread
From: Nathan Froyd @ 2010-12-06 18:18 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel

On Mon, Dec 06, 2010 at 05:00:06PM +0000, Peter Maydell wrote:
> The ARM architecture mandates that converting a NaN value to
> integer gives zero (if Invalid Operation FP exceptions are
> not being trapped). This isn't the behaviour of the SoftFloat
> library, so NaNs must be special-cased.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Nathan Froyd <froydnj@codesourcery.com>

-Nathan

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

end of thread, other threads:[~2010-12-06 18:18 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-12-06 17:00 [Qemu-devel] [PATCH V2 00/10] ARM: fix VCVT instructions Peter Maydell
2010-12-06 17:00 ` [Qemu-devel] [PATCH 01/10] ARM: Fix decoding of VFP forms of VCVT between float and int/fixed Peter Maydell
2010-12-06 17:00 ` [Qemu-devel] [PATCH 02/10] ARM: Fix decoding of Neon forms of VCVT between float and fixed point Peter Maydell
2010-12-06 17:00 ` [Qemu-devel] [PATCH 03/10] ARM: Fix sense of to_integer bit in Neon VCVT float/int conversion Peter Maydell
2010-12-06 17:00 ` [Qemu-devel] [PATCH 04/10] softfloat: Add float*_is_any_nan() functions Peter Maydell
2010-12-06 18:15   ` Nathan Froyd
2010-12-06 17:00 ` [Qemu-devel] [PATCH 05/10] ARM: Return correct result for float-to-integer conversion of NaN Peter Maydell
2010-12-06 18:18   ` Nathan Froyd
2010-12-06 17:00 ` [Qemu-devel] [PATCH 06/10] softfloat: Add float*_maybe_silence_nan() functions Peter Maydell
2010-12-06 18:16   ` Nathan Froyd
2010-12-06 17:00 ` [Qemu-devel] [PATCH 07/10] ARM: Return correct result for single<->double conversion of NaN Peter Maydell
2010-12-06 18:17   ` Nathan Froyd
2010-12-06 17:00 ` [Qemu-devel] [PATCH 08/10] ARM: Ignore top 16 bits when doing VCVT from 16 bit fixed point Peter Maydell
2010-12-06 17:00 ` [Qemu-devel] [PATCH 09/10] softfloat: Add float/double to 16 bit integer conversion functions Peter Maydell
2010-12-06 17:00 ` [Qemu-devel] [PATCH 10/10] ARM: Implement VCVT to 16 bit integer using new softfloat routines 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).