qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/8] ARM: fix VCVT instructions
@ 2010-11-11 18:23 Peter Maydell
  2010-11-11 18:23 ` [Qemu-devel] [PATCH 1/8] ARM: Fix decoding of VFP forms of VCVT between float and int/fixed Peter Maydell
                   ` (7 more replies)
  0 siblings, 8 replies; 16+ messages in thread
From: Peter Maydell @ 2010-11-11 18:23 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.

Peter Maydell (8):
  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
  ARM: Return correct result for float-to-integer conversion of NaN
  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.c        |  136 ++++++++++++++++++++++++++++++++++++++++++++++++
 fpu/softfloat.h        |    4 ++
 target-arm/helper.c    |   68 ++++++++++++++++++++++--
 target-arm/translate.c |   35 ++++++++-----
 4 files changed, 226 insertions(+), 17 deletions(-)

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

* [Qemu-devel] [PATCH 1/8] ARM: Fix decoding of VFP forms of VCVT between float and int/fixed
  2010-11-11 18:23 [Qemu-devel] [PATCH 0/8] ARM: fix VCVT instructions Peter Maydell
@ 2010-11-11 18:23 ` Peter Maydell
  2010-12-06 16:30   ` Nathan Froyd
  2010-11-11 18:23 ` [Qemu-devel] [PATCH 2/8] ARM: Fix decoding of Neon forms of VCVT between float and fixed point Peter Maydell
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Peter Maydell @ 2010-11-11 18:23 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>
---
 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.7.1

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

* [Qemu-devel] [PATCH 2/8] ARM: Fix decoding of Neon forms of VCVT between float and fixed point
  2010-11-11 18:23 [Qemu-devel] [PATCH 0/8] ARM: fix VCVT instructions Peter Maydell
  2010-11-11 18:23 ` [Qemu-devel] [PATCH 1/8] ARM: Fix decoding of VFP forms of VCVT between float and int/fixed Peter Maydell
@ 2010-11-11 18:23 ` Peter Maydell
  2010-11-11 18:23 ` [Qemu-devel] [PATCH 3/8] ARM: Fix sense of to_integer bit in Neon VCVT float/int conversion Peter Maydell
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 16+ messages in thread
From: Peter Maydell @ 2010-11-11 18:23 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>
---
 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.7.1

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

* [Qemu-devel] [PATCH 3/8] ARM: Fix sense of to_integer bit in Neon VCVT float/int conversion
  2010-11-11 18:23 [Qemu-devel] [PATCH 0/8] ARM: fix VCVT instructions Peter Maydell
  2010-11-11 18:23 ` [Qemu-devel] [PATCH 1/8] ARM: Fix decoding of VFP forms of VCVT between float and int/fixed Peter Maydell
  2010-11-11 18:23 ` [Qemu-devel] [PATCH 2/8] ARM: Fix decoding of Neon forms of VCVT between float and fixed point Peter Maydell
@ 2010-11-11 18:23 ` Peter Maydell
  2010-11-11 18:23 ` [Qemu-devel] [PATCH 4/8] ARM: Return correct result for float-to-integer conversion of NaN Peter Maydell
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 16+ messages in thread
From: Peter Maydell @ 2010-11-11 18:23 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 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.7.1

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

* [Qemu-devel] [PATCH 4/8] ARM: Return correct result for float-to-integer conversion of NaN
  2010-11-11 18:23 [Qemu-devel] [PATCH 0/8] ARM: fix VCVT instructions Peter Maydell
                   ` (2 preceding siblings ...)
  2010-11-11 18:23 ` [Qemu-devel] [PATCH 3/8] ARM: Fix sense of to_integer bit in Neon VCVT float/int conversion Peter Maydell
@ 2010-11-11 18:23 ` Peter Maydell
  2010-11-11 19:21   ` Nathan Froyd
  2010-11-11 18:23 ` [Qemu-devel] [PATCH 5/8] ARM: Return correct result for single<->double " Peter Maydell
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Peter Maydell @ 2010-11-11 18:23 UTC (permalink / raw)
  To: qemu-devel

The ARM architecture mandates that converting a NaN value to
integer gives zero. 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 |   44 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 44 insertions(+), 0 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 996d40d..72ba314 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2445,43 +2445,84 @@ float64 VFP_HELPER(sito, d)(float32 x, CPUState *env)
 }
 
 /* Float to integer conversion.  */
+
+/* Helper routines to identify NaNs. Note that softfloat's
+ * floatxx_is_nan() actually only returns true for quiet NaNs.
+ * A NaN has an exponent field all 1s and a fraction field
+ * anything except all zeros. Conveniently we can detect this
+ * by masking out the sign bit and doing an unsigned comparison.
+ */
+static int float32_is_any_nan(float32 x)
+{
+    return ((float32_val(x) & ~(1 << 31)) > 0x7f800000UL);
+}
+
+static int float64_is_any_nan(float64 x)
+{
+    return ((float64_val(x) & ~(1ULL << 63)) > 0x7ff0000000000000ULL);
+}
+
 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));
 }
 
@@ -2508,6 +2549,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.7.1

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

* [Qemu-devel] [PATCH 5/8] ARM: Return correct result for single<->double conversion of NaN
  2010-11-11 18:23 [Qemu-devel] [PATCH 0/8] ARM: fix VCVT instructions Peter Maydell
                   ` (3 preceding siblings ...)
  2010-11-11 18:23 ` [Qemu-devel] [PATCH 4/8] ARM: Return correct result for float-to-integer conversion of NaN Peter Maydell
@ 2010-11-11 18:23 ` Peter Maydell
  2010-11-11 18:24 ` [Qemu-devel] [PATCH 6/8] ARM: Ignore top 16 bits when doing VCVT from 16 bit fixed point Peter Maydell
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 16+ messages in thread
From: Peter Maydell @ 2010-11-11 18:23 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 |   20 ++++++++++++++++++--
 1 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 72ba314..628094f 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2529,12 +2529,28 @@ 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.
+     */
+    if (float64_is_signaling_nan(r)) 
+    {
+        return make_float64(float64_val(r) | (1LL << 51));
+    }
+    return 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.
+     */
+    if (float32_is_signaling_nan(r)) 
+    {
+        return make_float32(float32_val(r) | (1 << 22));
+    }
+    return r;
 }
 
 /* VFP3 fixed point conversion.  */
-- 
1.7.1

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

* [Qemu-devel] [PATCH 6/8] ARM: Ignore top 16 bits when doing VCVT from 16 bit fixed point
  2010-11-11 18:23 [Qemu-devel] [PATCH 0/8] ARM: fix VCVT instructions Peter Maydell
                   ` (4 preceding siblings ...)
  2010-11-11 18:23 ` [Qemu-devel] [PATCH 5/8] ARM: Return correct result for single<->double " Peter Maydell
@ 2010-11-11 18:24 ` Peter Maydell
  2010-11-11 18:24 ` [Qemu-devel] [PATCH 7/8] softfloat: Add float/double to 16 bit integer conversion functions Peter Maydell
  2010-11-11 18:24 ` [Qemu-devel] [PATCH 8/8] ARM: Implement VCVT to 16 bit integer using new softfloat routines Peter Maydell
  7 siblings, 0 replies; 16+ messages in thread
From: Peter Maydell @ 2010-11-11 18:24 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>
---
 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 628094f..66648d8 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2558,7 +2558,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.7.1

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

* [Qemu-devel] [PATCH 7/8] softfloat: Add float/double to 16 bit integer conversion functions
  2010-11-11 18:23 [Qemu-devel] [PATCH 0/8] ARM: fix VCVT instructions Peter Maydell
                   ` (5 preceding siblings ...)
  2010-11-11 18:24 ` [Qemu-devel] [PATCH 6/8] ARM: Ignore top 16 bits when doing VCVT from 16 bit fixed point Peter Maydell
@ 2010-11-11 18:24 ` Peter Maydell
  2010-11-11 18:24 ` [Qemu-devel] [PATCH 8/8] ARM: Implement VCVT to 16 bit integer using new softfloat routines Peter Maydell
  7 siblings, 0 replies; 16+ messages in thread
From: Peter Maydell @ 2010-11-11 18:24 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>
---
 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 9528825..5d68a07 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 );
@@ -321,6 +323,8 @@ INLINE int float32_is_zero(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.7.1

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

* [Qemu-devel] [PATCH 8/8] ARM: Implement VCVT to 16 bit integer using new softfloat routines
  2010-11-11 18:23 [Qemu-devel] [PATCH 0/8] ARM: fix VCVT instructions Peter Maydell
                   ` (6 preceding siblings ...)
  2010-11-11 18:24 ` [Qemu-devel] [PATCH 7/8] softfloat: Add float/double to 16 bit integer conversion functions Peter Maydell
@ 2010-11-11 18:24 ` Peter Maydell
  7 siblings, 0 replies; 16+ messages in thread
From: Peter Maydell @ 2010-11-11 18:24 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>
---
 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 66648d8..5fa5f40 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2569,7 +2569,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.7.1

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

* Re: [Qemu-devel] [PATCH 4/8] ARM: Return correct result for float-to-integer conversion of NaN
  2010-11-11 18:23 ` [Qemu-devel] [PATCH 4/8] ARM: Return correct result for float-to-integer conversion of NaN Peter Maydell
@ 2010-11-11 19:21   ` Nathan Froyd
  2010-11-12 23:08     ` Peter Maydell
  0 siblings, 1 reply; 16+ messages in thread
From: Nathan Froyd @ 2010-11-11 19:21 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel

On Thu, Nov 11, 2010 at 06:23:58PM +0000, Peter Maydell wrote:
> The ARM architecture mandates that converting a NaN value to
> integer gives zero. This isn't the behaviour of the SoftFloat
> library, so NaNs must be special-cased.

This is correct, but it's really only correct if FP traps are disabled.

(Also, the arm routines returning float* values is just awful.  Not your
fault, just a comment.)

-Nathan

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

* Re: [Qemu-devel] [PATCH 4/8] ARM: Return correct result for float-to-integer conversion of NaN
  2010-11-11 19:21   ` Nathan Froyd
@ 2010-11-12 23:08     ` Peter Maydell
  0 siblings, 0 replies; 16+ messages in thread
From: Peter Maydell @ 2010-11-12 23:08 UTC (permalink / raw)
  To: Nathan Froyd; +Cc: qemu-devel

On 11 November 2010 19:21, Nathan Froyd <froydnj@codesourcery.com> wrote:
> On Thu, Nov 11, 2010 at 06:23:58PM +0000, Peter Maydell wrote:
>> The ARM architecture mandates that converting a NaN value to
>> integer gives zero. This isn't the behaviour of the SoftFloat
>> library, so NaNs must be special-cased.
>
> This is correct, but it's really only correct if FP traps are disabled.

True (in that if you take a trap you don't return any result at all),
but isn't it a bit of a red herring for this patchset given that qemu
doesn't implement trapping on FP exceptions?

I can make the commit message read "gives zero (if Invalid
Operation FP exceptions are not being trapped)" if you think
that would be clearer.

-- PMM

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

* Re: [Qemu-devel] [PATCH 1/8] ARM: Fix decoding of VFP forms of VCVT between float and int/fixed
  2010-11-11 18:23 ` [Qemu-devel] [PATCH 1/8] ARM: Fix decoding of VFP forms of VCVT between float and int/fixed Peter Maydell
@ 2010-12-06 16:30   ` Nathan Froyd
  2010-12-06 16:48     ` Peter Maydell
  0 siblings, 1 reply; 16+ messages in thread
From: Nathan Froyd @ 2010-12-06 16:30 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel

On Thu, Nov 11, 2010 at 06:23:55PM +0000, Peter Maydell wrote:
> 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>

I don't know how good QEMU's framework is, but it'd be nice to have your
testing code checked into the tree, in case anybody decides to do major
surgery on the ARM backend.

-Nathan

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

* Re: [Qemu-devel] [PATCH 1/8] ARM: Fix decoding of VFP forms of VCVT between float and int/fixed
  2010-12-06 16:30   ` Nathan Froyd
@ 2010-12-06 16:48     ` Peter Maydell
  2010-12-06 16:57       ` Nathan Froyd
  0 siblings, 1 reply; 16+ messages in thread
From: Peter Maydell @ 2010-12-06 16:48 UTC (permalink / raw)
  To: Nathan Froyd; +Cc: qemu-devel

On 6 December 2010 16:30, Nathan Froyd <froydnj@codesourcery.com> wrote:
> On Thu, Nov 11, 2010 at 06:23:55PM +0000, Peter Maydell wrote:
>> 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>

Thanks. I'll resend this set with the softfloat-related comments addressed
for the two patches that affects (and the remaining unchanged patches
with your Reviewed-by: tag on them).

> I don't know how good QEMU's framework is, but it'd be nice to have your
> testing code checked into the tree, in case anybody decides to do major
> surgery on the ARM backend.

I'm not sure how well it would fit into being committed to qemu (yet):
it works as a program where you run half of it on real ARM hardware
and the other half under qemu (or valgrind) and it compares register
results after executing instructions by looking at the sigcontext struct
in a signal handler. Plus there's a perl script to generate random
instruction set sequences to feed the test program. It could be made
more automated and independent of having a reference bit of hardware
but I haven't got round to that yet. (Also since it has utility outside of
just testing qemu I'm not sure if it really belongs in the qemu repo.)

-- PMM

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

* Re: [Qemu-devel] [PATCH 1/8] ARM: Fix decoding of VFP forms of VCVT between float and int/fixed
  2010-12-06 16:48     ` Peter Maydell
@ 2010-12-06 16:57       ` Nathan Froyd
  2010-12-06 17:07         ` Peter Maydell
  0 siblings, 1 reply; 16+ messages in thread
From: Nathan Froyd @ 2010-12-06 16:57 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel

On Mon, Dec 06, 2010 at 04:48:25PM +0000, Peter Maydell wrote:
> I'm not sure how well it would fit into being committed to qemu (yet):
> it works as a program where you run half of it on real ARM hardware
> and the other half under qemu (or valgrind) and it compares register
> results after executing instructions by looking at the sigcontext struct
> in a signal handler. Plus there's a perl script to generate random
> instruction set sequences to feed the test program. It could be made
> more automated and independent of having a reference bit of hardware
> but I haven't got round to that yet. (Also since it has utility outside of
> just testing qemu I'm not sure if it really belongs in the qemu repo.)

That does sound a little heavyweight.  Scripting gdb is also a possibility.

FWIW--and this is not particularly conducive to random insn
sequences--the approach taken when doing the AltiVec bits was to have
code that looked like:

  for each insn:
     for a suitable set of inputs:
        setup interesting registers (status control registers etc.)
        load inputs into registers
        execute
        record interesting post conditions in file.out

You'd get an output file from real hardware and an output file from the
simulator and then compare them, fixing differences as you go.  The
actual code included bits to compare the files as well as doing the
generation.

The output files can be somewhat large, but I'm sure clever engineering
could be applied to make them smaller.

Of course, the *real* problems are in undefined-behavior land. :)

-Nathan

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

* Re: [Qemu-devel] [PATCH 1/8] ARM: Fix decoding of VFP forms of VCVT between float and int/fixed
  2010-12-06 16:57       ` Nathan Froyd
@ 2010-12-06 17:07         ` Peter Maydell
  2010-12-08 12:00           ` Peter Maydell
  0 siblings, 1 reply; 16+ messages in thread
From: Peter Maydell @ 2010-12-06 17:07 UTC (permalink / raw)
  To: Nathan Froyd; +Cc: qemu-devel

On 6 December 2010 16:57, Nathan Froyd <froydnj@codesourcery.com> wrote:
> FWIW--and this is not particularly conducive to random insn
> sequences--the approach taken when doing the AltiVec bits was to have
> code that looked like:
>
>  for each insn:
>     for a suitable set of inputs:
>        setup interesting registers (status control registers etc.)
>        load inputs into registers
>        execute
>        record interesting post conditions in file.out

Mmm. The trouble with that is it's more faff per instruction than I'd
like. The nice thing about random instruction sequences is you can
have a config file that says:
VQSHL_reg_a A1 1111 001 u 0 d sz:2 vn:4 vd:4 0100 n 0 m 1 vm:4
VQSHL_reg_b A1 1111 001 u 0 d sz:2 vn:3 0 vd:3 0 0100 n 1 m 1 vm:3 0

and that's all you need to test the VQSHL(reg) forms, and it's basically
the instruction format out of the ARM ARM. (In fact it ought to be a
single line but qemu doesn't correctly UNDEF on the Q==1, lsbit of
Vd/Vn/Vm!=0 case so I am avoiding generating it.)

> You'd get an output file from real hardware and an output file from the
> simulator and then compare them, fixing differences as you go.  The
> actual code included bits to compare the files as well as doing the
> generation.

You could certainly do the 'record/replay file' part; at the moment
what I have does about what I want, though :-).
(I really must get round to writing the README and sticking it
in a public git repo.)

> Of course, the *real* problems are in undefined-behavior land. :)

Heh. We don't even correctly handle "entirely well defined and should
UNDEF" land yet...

-- PMM

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

* Re: [Qemu-devel] [PATCH 1/8] ARM: Fix decoding of VFP forms of VCVT between float and int/fixed
  2010-12-06 17:07         ` Peter Maydell
@ 2010-12-08 12:00           ` Peter Maydell
  0 siblings, 0 replies; 16+ messages in thread
From: Peter Maydell @ 2010-12-08 12:00 UTC (permalink / raw)
  To: Nathan Froyd; +Cc: qemu-devel

On 6 December 2010 17:07, Peter Maydell <peter.maydell@linaro.org> wrote:
(regarding my random-instruction-sequence testing tool)
> (I really must get round to writing the README and sticking it
> in a public git repo.)

The curious can find it here:

http://git.linaro.org/gitweb?p=people/pmaydell/risu.git;a=summary

-- PMM

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

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

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-11-11 18:23 [Qemu-devel] [PATCH 0/8] ARM: fix VCVT instructions Peter Maydell
2010-11-11 18:23 ` [Qemu-devel] [PATCH 1/8] ARM: Fix decoding of VFP forms of VCVT between float and int/fixed Peter Maydell
2010-12-06 16:30   ` Nathan Froyd
2010-12-06 16:48     ` Peter Maydell
2010-12-06 16:57       ` Nathan Froyd
2010-12-06 17:07         ` Peter Maydell
2010-12-08 12:00           ` Peter Maydell
2010-11-11 18:23 ` [Qemu-devel] [PATCH 2/8] ARM: Fix decoding of Neon forms of VCVT between float and fixed point Peter Maydell
2010-11-11 18:23 ` [Qemu-devel] [PATCH 3/8] ARM: Fix sense of to_integer bit in Neon VCVT float/int conversion Peter Maydell
2010-11-11 18:23 ` [Qemu-devel] [PATCH 4/8] ARM: Return correct result for float-to-integer conversion of NaN Peter Maydell
2010-11-11 19:21   ` Nathan Froyd
2010-11-12 23:08     ` Peter Maydell
2010-11-11 18:23 ` [Qemu-devel] [PATCH 5/8] ARM: Return correct result for single<->double " Peter Maydell
2010-11-11 18:24 ` [Qemu-devel] [PATCH 6/8] ARM: Ignore top 16 bits when doing VCVT from 16 bit fixed point Peter Maydell
2010-11-11 18:24 ` [Qemu-devel] [PATCH 7/8] softfloat: Add float/double to 16 bit integer conversion functions Peter Maydell
2010-11-11 18:24 ` [Qemu-devel] [PATCH 8/8] 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).