All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/6] target-arm: Fix floating point conversions
@ 2011-02-09 16:27 Peter Maydell
  2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 1/6] softfloat: Add float16 type and float16 NaN handling functions Peter Maydell
                   ` (5 more replies)
  0 siblings, 6 replies; 15+ messages in thread
From: Peter Maydell @ 2011-02-09 16:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: Christophe Lyon, patches

This patchset fixes two issues:
 * default_nan_mode not being honoured for float-to-float conversions
 * half precision conversions being broken in a number of ways as
   well as not handling default_nan_mode.

With this patchset qemu passes random-instruction-selection tests
for VCVT.F32.F16, VCVT.F16.F32, VCVTB and VCVTT, in both IEEE and
non-IEEE modes, with and without default-NaN behaviour.

Christophe: this patchset includes your softfloat v3 patch, although
I have split it up a little to keep the float16 bits separate.

No change from v1 except that I have fixed the attributions on
patch 2/6, which I got wrong the first time around :-(

Christophe Lyon (1):
  softfloat: Honour default_nan_mode for float-to-float conversions

Peter Maydell (5):
  softfloat: Add float16 type and float16 NaN handling functions
  softfloat: Fix single-to-half precision float conversions
  softfloat: Correctly handle NaNs in float16_to_float32()
  target-arm: Silence NaNs resulting from half-precision conversions
  target-arm: Use standard FPSCR for Neon half-precision operations

 fpu/softfloat-specialize.h |  125 ++++++++++++++++++++++++++++++++++++++++++--
 fpu/softfloat.c            |   66 ++++++++++++-----------
 fpu/softfloat.h            |   12 ++++-
 target-arm/helper.c        |   38 +++++++++++--
 target-arm/helpers.h       |    2 +
 target-arm/translate.c     |   16 +++---
 6 files changed, 208 insertions(+), 51 deletions(-)

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

* [Qemu-devel] [PATCH v2 1/6] softfloat: Add float16 type and float16 NaN handling functions
  2011-02-09 16:27 [Qemu-devel] [PATCH v2 0/6] target-arm: Fix floating point conversions Peter Maydell
@ 2011-02-09 16:27 ` Peter Maydell
  2011-02-09 18:40   ` Aurelien Jarno
  2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 2/6] softfloat: Honour default_nan_mode for float-to-float conversions Peter Maydell
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 15+ messages in thread
From: Peter Maydell @ 2011-02-09 16:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: Christophe Lyon, patches

Add a float16 type to softfloat, rather than using bits16 directly.
Also add the missing functions float16_is_quiet_nan(),
float16_is_signaling_nan() and float16_maybe_silence_nan(),
which are needed for the float16 conversion routines.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 fpu/softfloat-specialize.h |   59 ++++++++++++++++++++++++++++++++++++++++++++
 fpu/softfloat.c            |    8 +++---
 fpu/softfloat.h            |   12 +++++++-
 3 files changed, 73 insertions(+), 6 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index eb644b2..bc9a66c 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -57,6 +57,65 @@ typedef struct {
 } commonNaNT;
 
 /*----------------------------------------------------------------------------
+| The pattern for a default generated half-precision NaN.
+*----------------------------------------------------------------------------*/
+#if defined(TARGET_ARM)
+#define float16_default_nan 0x7E00
+#elif SNAN_BIT_IS_ONE
+#define float16_default_nan 0x7DFF
+#else
+#define float16_default_nan 0xFE00
+#endif
+
+/*----------------------------------------------------------------------------
+| Returns 1 if the half-precision floating-point value `a' is a quiet
+| NaN; otherwise returns 0.
+*----------------------------------------------------------------------------*/
+
+int float16_is_quiet_nan(float16 a)
+{
+#if SNAN_BIT_IS_ONE
+    return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
+#else
+    return ((a & ~0x8000) >= 0x7c80);
+#endif
+}
+
+/*----------------------------------------------------------------------------
+| Returns 1 if the half-precision floating-point value `a' is a signaling
+| NaN; otherwise returns 0.
+*----------------------------------------------------------------------------*/
+
+int float16_is_signaling_nan(float16 a)
+{
+#if SNAN_BIT_IS_ONE
+    return ((a & ~0x8000) >= 0x7c80);
+#else
+    return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
+#endif
+}
+
+/*----------------------------------------------------------------------------
+| Returns a quiet NaN if the half-precision floating point value `a' is a
+| signaling NaN; otherwise returns `a'.
+*----------------------------------------------------------------------------*/
+float16 float16_maybe_silence_nan(float16 a)
+{
+    if (float16_is_signaling_nan(a)) {
+#if SNAN_BIT_IS_ONE
+#  if defined(TARGET_MIPS) || defined(TARGET_SH4)
+        return float16_default_nan;
+#  else
+#    error Rules for silencing a signaling NaN are target-specific
+#  endif
+#else
+        a |= (1 << 9);
+#endif
+    }
+    return a;
+}
+
+/*----------------------------------------------------------------------------
 | The pattern for a default generated single-precision NaN.
 *----------------------------------------------------------------------------*/
 #if defined(TARGET_SPARC)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 17842f4..dc4492a 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -2713,15 +2713,15 @@ float32 float64_to_float32( float64 a STATUS_PARAM )
 | than the desired result exponent whenever `zSig' is a complete, normalized
 | significand.
 *----------------------------------------------------------------------------*/
-static bits16 packFloat16(flag zSign, int16 zExp, bits16 zSig)
+static float16 packFloat16(flag zSign, int16 zExp, bits16 zSig)
 {
     return (((bits32)zSign) << 15) + (((bits32)zExp) << 10) + zSig;
 }
 
 /* Half precision floats come in two formats: standard IEEE and "ARM" format.
    The latter gains extra exponent range by omitting the NaN/Inf encodings.  */
-  
-float32 float16_to_float32( bits16 a, flag ieee STATUS_PARAM )
+
+float32 float16_to_float32(float16 a, flag ieee STATUS_PARAM)
 {
     flag aSign;
     int16 aExp;
@@ -2753,7 +2753,7 @@ float32 float16_to_float32( bits16 a, flag ieee STATUS_PARAM )
     return packFloat32( aSign, aExp + 0x70, aSig << 13);
 }
 
-bits16 float32_to_float16( float32 a, flag ieee STATUS_PARAM)
+float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM)
 {
     flag aSign;
     int16 aExp;
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index 4a5345c..f773d67 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -118,6 +118,7 @@ enum {
    sane ABI should be able to see though these structs.  However
    x86/gcc 3.x seems to struggle a bit, so leave them disabled by default.  */
 //#define USE_SOFTFLOAT_STRUCT_TYPES
+typedef uint16_t float16;
 #ifdef USE_SOFTFLOAT_STRUCT_TYPES
 typedef struct {
     uint32_t v;
@@ -253,8 +254,15 @@ float128 int64_to_float128( int64_t STATUS_PARAM );
 /*----------------------------------------------------------------------------
 | Software half-precision conversion routines.
 *----------------------------------------------------------------------------*/
-bits16 float32_to_float16( float32, flag STATUS_PARAM );
-float32 float16_to_float32( bits16, flag STATUS_PARAM );
+float16 float32_to_float16( float32, flag STATUS_PARAM );
+float32 float16_to_float32( float16, flag STATUS_PARAM );
+
+/*----------------------------------------------------------------------------
+| Software half-precision operations.
+*----------------------------------------------------------------------------*/
+int float16_is_quiet_nan( float16 );
+int float16_is_signaling_nan( float16 );
+float16 float16_maybe_silence_nan( float16 );
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE single-precision conversion routines.
-- 
1.7.1

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

* [Qemu-devel] [PATCH v2 2/6] softfloat: Honour default_nan_mode for float-to-float conversions
  2011-02-09 16:27 [Qemu-devel] [PATCH v2 0/6] target-arm: Fix floating point conversions Peter Maydell
  2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 1/6] softfloat: Add float16 type and float16 NaN handling functions Peter Maydell
@ 2011-02-09 16:27 ` Peter Maydell
  2011-02-09 18:40   ` Aurelien Jarno
  2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 3/6] softfloat: Fix single-to-half precision float conversions Peter Maydell
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 15+ messages in thread
From: Peter Maydell @ 2011-02-09 16:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: Christophe Lyon, patches

From: Christophe Lyon <christophe.lyon@st.com>

Honour the default_nan_mode flag when doing conversions between
different floating point formats, as well as when returning a NaN from
a two-operand floating point function. This corrects the behaviour
of float<->double conversions on both ARM and SH4.

Signed-off-by: Christophe Lyon <christophe.lyon@st.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
 fpu/softfloat-specialize.h |   29 +++++++++++++++++++++++++----
 fpu/softfloat.c            |   24 ++++++++++++------------
 2 files changed, 37 insertions(+), 16 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index bc9a66c..2f65b9d 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -203,9 +203,14 @@ static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )
 | precision floating-point format.
 *----------------------------------------------------------------------------*/
 
-static float32 commonNaNToFloat32( commonNaNT a )
+static float32 commonNaNToFloat32( commonNaNT a STATUS_PARAM)
 {
     bits32 mantissa = a.high>>41;
+
+    if ( STATUS(default_nan_mode) ) {
+        return float32_default_nan;
+    }
+
     if ( mantissa )
         return make_float32(
             ( ( (bits32) a.sign )<<31 ) | 0x7F800000 | ( a.high>>41 ) );
@@ -457,10 +462,14 @@ static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM)
 | precision floating-point format.
 *----------------------------------------------------------------------------*/
 
-static float64 commonNaNToFloat64( commonNaNT a )
+static float64 commonNaNToFloat64( commonNaNT a STATUS_PARAM)
 {
     bits64 mantissa = a.high>>12;
 
+    if ( STATUS(default_nan_mode) ) {
+        return float64_default_nan;
+    }
+
     if ( mantissa )
         return make_float64(
               ( ( (bits64) a.sign )<<63 )
@@ -614,10 +623,16 @@ static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM)
 | double-precision floating-point format.
 *----------------------------------------------------------------------------*/
 
-static floatx80 commonNaNToFloatx80( commonNaNT a )
+static floatx80 commonNaNToFloatx80( commonNaNT a STATUS_PARAM)
 {
     floatx80 z;
 
+    if ( STATUS(default_nan_mode) ) {
+        z.low = floatx80_default_nan_low;
+        z.high = floatx80_default_nan_high;
+        return z;
+    }
+
     if (a.high)
         z.low = a.high;
     else
@@ -762,10 +777,16 @@ static commonNaNT float128ToCommonNaN( float128 a STATUS_PARAM)
 | precision floating-point format.
 *----------------------------------------------------------------------------*/
 
-static float128 commonNaNToFloat128( commonNaNT a )
+static float128 commonNaNToFloat128( commonNaNT a STATUS_PARAM)
 {
     float128 z;
 
+    if ( STATUS(default_nan_mode) ) {
+        z.low = float128_default_nan_low;
+        z.high = float128_default_nan_high;
+        return z;
+    }
+
     shift128Right( a.high, a.low, 16, &z.high, &z.low );
     z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF000000000000 );
     return z;
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index dc4492a..c3058f4 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -1534,7 +1534,7 @@ float64 float32_to_float64( float32 a STATUS_PARAM )
     aExp = extractFloat32Exp( a );
     aSign = extractFloat32Sign( a );
     if ( aExp == 0xFF ) {
-        if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a STATUS_VAR ));
+        if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
         return packFloat64( aSign, 0x7FF, 0 );
     }
     if ( aExp == 0 ) {
@@ -1566,7 +1566,7 @@ floatx80 float32_to_floatx80( float32 a STATUS_PARAM )
     aExp = extractFloat32Exp( a );
     aSign = extractFloat32Sign( a );
     if ( aExp == 0xFF ) {
-        if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a STATUS_VAR ) );
+        if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
         return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
     }
     if ( aExp == 0 ) {
@@ -1600,7 +1600,7 @@ float128 float32_to_float128( float32 a STATUS_PARAM )
     aExp = extractFloat32Exp( a );
     aSign = extractFloat32Sign( a );
     if ( aExp == 0xFF ) {
-        if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a STATUS_VAR ) );
+        if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
         return packFloat128( aSign, 0x7FFF, 0, 0 );
     }
     if ( aExp == 0 ) {
@@ -2689,7 +2689,7 @@ float32 float64_to_float32( float64 a STATUS_PARAM )
     aExp = extractFloat64Exp( a );
     aSign = extractFloat64Sign( a );
     if ( aExp == 0x7FF ) {
-        if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a STATUS_VAR ) );
+        if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
         return packFloat32( aSign, 0xFF, 0 );
     }
     shift64RightJamming( aSig, 22, &aSig );
@@ -2861,7 +2861,7 @@ floatx80 float64_to_floatx80( float64 a STATUS_PARAM )
     aExp = extractFloat64Exp( a );
     aSign = extractFloat64Sign( a );
     if ( aExp == 0x7FF ) {
-        if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a STATUS_VAR ) );
+        if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
         return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
     }
     if ( aExp == 0 ) {
@@ -2896,7 +2896,7 @@ float128 float64_to_float128( float64 a STATUS_PARAM )
     aExp = extractFloat64Exp( a );
     aSign = extractFloat64Sign( a );
     if ( aExp == 0x7FF ) {
-        if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a STATUS_VAR ) );
+        if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
         return packFloat128( aSign, 0x7FFF, 0, 0 );
     }
     if ( aExp == 0 ) {
@@ -3843,7 +3843,7 @@ float32 floatx80_to_float32( floatx80 a STATUS_PARAM )
     aSign = extractFloatx80Sign( a );
     if ( aExp == 0x7FFF ) {
         if ( (bits64) ( aSig<<1 ) ) {
-            return commonNaNToFloat32( floatx80ToCommonNaN( a STATUS_VAR ) );
+            return commonNaNToFloat32( floatx80ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
         }
         return packFloat32( aSign, 0xFF, 0 );
     }
@@ -3871,7 +3871,7 @@ float64 floatx80_to_float64( floatx80 a STATUS_PARAM )
     aSign = extractFloatx80Sign( a );
     if ( aExp == 0x7FFF ) {
         if ( (bits64) ( aSig<<1 ) ) {
-            return commonNaNToFloat64( floatx80ToCommonNaN( a STATUS_VAR ) );
+            return commonNaNToFloat64( floatx80ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
         }
         return packFloat64( aSign, 0x7FF, 0 );
     }
@@ -3900,7 +3900,7 @@ float128 floatx80_to_float128( floatx80 a STATUS_PARAM )
     aExp = extractFloatx80Exp( a );
     aSign = extractFloatx80Sign( a );
     if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) {
-        return commonNaNToFloat128( floatx80ToCommonNaN( a STATUS_VAR ) );
+        return commonNaNToFloat128( floatx80ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
     }
     shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 );
     return packFloat128( aSign, aExp, zSig0, zSig1 );
@@ -4863,7 +4863,7 @@ float32 float128_to_float32( float128 a STATUS_PARAM )
     aSign = extractFloat128Sign( a );
     if ( aExp == 0x7FFF ) {
         if ( aSig0 | aSig1 ) {
-            return commonNaNToFloat32( float128ToCommonNaN( a STATUS_VAR ) );
+            return commonNaNToFloat32( float128ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
         }
         return packFloat32( aSign, 0xFF, 0 );
     }
@@ -4897,7 +4897,7 @@ float64 float128_to_float64( float128 a STATUS_PARAM )
     aSign = extractFloat128Sign( a );
     if ( aExp == 0x7FFF ) {
         if ( aSig0 | aSig1 ) {
-            return commonNaNToFloat64( float128ToCommonNaN( a STATUS_VAR ) );
+            return commonNaNToFloat64( float128ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
         }
         return packFloat64( aSign, 0x7FF, 0 );
     }
@@ -4932,7 +4932,7 @@ floatx80 float128_to_floatx80( float128 a STATUS_PARAM )
     aSign = extractFloat128Sign( a );
     if ( aExp == 0x7FFF ) {
         if ( aSig0 | aSig1 ) {
-            return commonNaNToFloatx80( float128ToCommonNaN( a STATUS_VAR ) );
+            return commonNaNToFloatx80( float128ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
         }
         return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
     }
-- 
1.7.1

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

* [Qemu-devel] [PATCH v2 3/6] softfloat: Fix single-to-half precision float conversions
  2011-02-09 16:27 [Qemu-devel] [PATCH v2 0/6] target-arm: Fix floating point conversions Peter Maydell
  2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 1/6] softfloat: Add float16 type and float16 NaN handling functions Peter Maydell
  2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 2/6] softfloat: Honour default_nan_mode for float-to-float conversions Peter Maydell
@ 2011-02-09 16:27 ` Peter Maydell
  2011-02-09 18:41   ` Aurelien Jarno
  2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 4/6] softfloat: Correctly handle NaNs in float16_to_float32() Peter Maydell
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 15+ messages in thread
From: Peter Maydell @ 2011-02-09 16:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: Christophe Lyon, patches

Fix various bugs in the single-to-half-precision conversion code:
 * input NaNs not correctly converted in IEEE mode
   (fixed by defining and using a commonNaNToFloat16())
 * wrong values returned when converting NaN/Inf into non-IEEE
   half precision value
 * wrong values returned for conversion of values which are
   on the boundary between denormal and zero for the half
   precision format
 * zeroes not correctly identified
 * excessively large results in non-IEEE mode should
   generate InvalidOp, not Overflow

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

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 2f65b9d..4907484 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -116,6 +116,26 @@ float16 float16_maybe_silence_nan(float16 a)
 }
 
 /*----------------------------------------------------------------------------
+| Returns the result of converting the canonical NaN `a' to the half-
+| precision floating-point format.
+*----------------------------------------------------------------------------*/
+
+static float16 commonNaNToFloat16(commonNaNT a STATUS_PARAM)
+{
+    uint16_t mantissa = a.high>>54;
+
+    if (STATUS(default_nan_mode)) {
+        return float16_default_nan;
+    }
+
+    if (mantissa) {
+        return ((((uint16_t) a.sign) << 15) | (0x1F << 10) | mantissa);
+    } else {
+        return float16_default_nan;
+    }
+}
+
+/*----------------------------------------------------------------------------
 | The pattern for a default generated single-precision NaN.
 *----------------------------------------------------------------------------*/
 #if defined(TARGET_SPARC)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index c3058f4..4d51428 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -2767,25 +2767,31 @@ float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM)
     aExp = extractFloat32Exp( a );
     aSign = extractFloat32Sign( a );
     if ( aExp == 0xFF ) {
-        if (aSig) {
-            /* Make sure correct exceptions are raised.  */
-            float32ToCommonNaN(a STATUS_VAR);
-            aSig |= 0x00400000;
+        if ( aSig ) {
+            /* Input is a NaN */
+            bits16 r = commonNaNToFloat16( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
+            if (!ieee) {
+                return packFloat16(aSign, 0, 0);
+            }
+            return r;
         }
-        return packFloat16(aSign, 0x1f, aSig >> 13);
+        /* Infinity */
+        if (!ieee) {
+            float_raise(float_flag_invalid STATUS_VAR);
+            return packFloat16(aSign, 0x1f, 0x3ff);
+        }
+        return packFloat16(aSign, 0x1f, 0);
     }
-    if (aExp == 0 && aSign == 0) {
+    if (aExp == 0 && aSig == 0) {
         return packFloat16(aSign, 0, 0);
     }
     /* Decimal point between bits 22 and 23.  */
     aSig |= 0x00800000;
     aExp -= 0x7f;
     if (aExp < -14) {
-        mask = 0x007fffff;
-        if (aExp < -24) {
-            aExp = -25;
-        } else {
-            mask >>= 24 + aExp;
+        mask = 0x00ffffff;
+        if (aExp >= -24) {
+            mask >>= 25 + aExp;
         }
     } else {
         mask = 0x00001fff;
@@ -2827,7 +2833,7 @@ float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM)
         }
     } else {
         if (aExp > 16) {
-            float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR);
+            float_raise(float_flag_invalid | float_flag_inexact STATUS_VAR);
             return packFloat16(aSign, 0x1f, 0x3ff);
         }
     }
-- 
1.7.1

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

* [Qemu-devel] [PATCH v2 4/6] softfloat: Correctly handle NaNs in float16_to_float32()
  2011-02-09 16:27 [Qemu-devel] [PATCH v2 0/6] target-arm: Fix floating point conversions Peter Maydell
                   ` (2 preceding siblings ...)
  2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 3/6] softfloat: Fix single-to-half precision float conversions Peter Maydell
@ 2011-02-09 16:27 ` Peter Maydell
  2011-02-09 18:42   ` Aurelien Jarno
  2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 5/6] target-arm: Silence NaNs resulting from half-precision conversions Peter Maydell
  2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 6/6] target-arm: Use standard FPSCR for Neon half-precision operations Peter Maydell
  5 siblings, 1 reply; 15+ messages in thread
From: Peter Maydell @ 2011-02-09 16:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: Christophe Lyon, patches

Correctly handle NaNs in float16_to_float32(), by defining and
using a float16ToCommonNaN() function, as we do with the other formats.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 fpu/softfloat-specialize.h |   17 +++++++++++++++++
 fpu/softfloat.c            |    4 +---
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 4907484..af82359 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -116,6 +116,23 @@ float16 float16_maybe_silence_nan(float16 a)
 }
 
 /*----------------------------------------------------------------------------
+| Returns the result of converting the half-precision floating-point NaN
+| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
+| exception is raised.
+*----------------------------------------------------------------------------*/
+
+static commonNaNT float16ToCommonNaN( float16 a STATUS_PARAM )
+{
+    commonNaNT z;
+
+    if ( float16_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR );
+    z.sign = a >> 15;
+    z.low = 0;
+    z.high = ((bits64) a)<<54;
+    return z;
+}
+
+/*----------------------------------------------------------------------------
 | Returns the result of converting the canonical NaN `a' to the half-
 | precision floating-point format.
 *----------------------------------------------------------------------------*/
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 4d51428..735db38 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -2733,9 +2733,7 @@ float32 float16_to_float32(float16 a, flag ieee STATUS_PARAM)
 
     if (aExp == 0x1f && ieee) {
         if (aSig) {
-            /* Make sure correct exceptions are raised.  */
-            float32ToCommonNaN(a STATUS_VAR);
-            aSig |= 0x200;
+            return commonNaNToFloat32(float16ToCommonNaN(a STATUS_VAR) STATUS_VAR);
         }
         return packFloat32(aSign, 0xff, aSig << 13);
     }
-- 
1.7.1

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

* [Qemu-devel] [PATCH v2 5/6] target-arm: Silence NaNs resulting from half-precision conversions
  2011-02-09 16:27 [Qemu-devel] [PATCH v2 0/6] target-arm: Fix floating point conversions Peter Maydell
                   ` (3 preceding siblings ...)
  2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 4/6] softfloat: Correctly handle NaNs in float16_to_float32() Peter Maydell
@ 2011-02-09 16:27 ` Peter Maydell
  2011-02-09 18:42   ` Aurelien Jarno
  2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 6/6] target-arm: Use standard FPSCR for Neon half-precision operations Peter Maydell
  5 siblings, 1 reply; 15+ messages in thread
From: Peter Maydell @ 2011-02-09 16:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: Christophe Lyon, patches

Silence the NaNs that may result from half-precision conversion,
as we do for the other conversions.

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 d46defc..503278c 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2627,14 +2627,22 @@ float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, CPUState *env)
 {
     float_status *s = &env->vfp.fp_status;
     int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
-    return float16_to_float32(a, ieee, s);
+    float32 r = float16_to_float32(a, ieee, s);
+    if (ieee) {
+        return float32_maybe_silence_nan(r);
+    }
+    return r;
 }
 
 uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, CPUState *env)
 {
     float_status *s = &env->vfp.fp_status;
     int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
-    return float32_to_float16(a, ieee, s);
+    float16 r = float32_to_float16(a, ieee, s);
+    if (ieee) {
+        return float16_maybe_silence_nan(r);
+    }
+    return r;
 }
 
 float32 HELPER(recps_f32)(float32 a, float32 b, CPUState *env)
-- 
1.7.1

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

* [Qemu-devel] [PATCH v2 6/6] target-arm: Use standard FPSCR for Neon half-precision operations
  2011-02-09 16:27 [Qemu-devel] [PATCH v2 0/6] target-arm: Fix floating point conversions Peter Maydell
                   ` (4 preceding siblings ...)
  2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 5/6] target-arm: Silence NaNs resulting from half-precision conversions Peter Maydell
@ 2011-02-09 16:27 ` Peter Maydell
  2011-02-09 18:43   ` Aurelien Jarno
  2011-02-09 19:03   ` Peter Maydell
  5 siblings, 2 replies; 15+ messages in thread
From: Peter Maydell @ 2011-02-09 16:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: Christophe Lyon, patches

The Neon half-precision conversion operations (VCVT.F16.F32 and
VCVT.F32.F16) use ARM standard floating-point arithmetic, unlike
the VFP versions (VCVTB and VCVTT).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/helper.c    |   26 ++++++++++++++++++++++----
 target-arm/helpers.h   |    2 ++
 target-arm/translate.c |   16 ++++++++--------
 3 files changed, 32 insertions(+), 12 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 503278c..d36f0f3 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2623,9 +2623,8 @@ VFP_CONV_FIX(ul, s, float32, uint32, u)
 #undef VFP_CONV_FIX
 
 /* Half precision conversions.  */
-float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, CPUState *env)
+static float32 do_fcvt_f16_to_f32(uint32_t a, CPUState *env, float_status *s)
 {
-    float_status *s = &env->vfp.fp_status;
     int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
     float32 r = float16_to_float32(a, ieee, s);
     if (ieee) {
@@ -2634,9 +2633,8 @@ float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, CPUState *env)
     return r;
 }
 
-uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, CPUState *env)
+static uint32_t do_fcvt_f32_to_f16(float32 a, CPUState *env, float_status *s)
 {
-    float_status *s = &env->vfp.fp_status;
     int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
     float16 r = float32_to_float16(a, ieee, s);
     if (ieee) {
@@ -2645,6 +2643,26 @@ uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, CPUState *env)
     return r;
 }
 
+float32 HELPER(neon_fcvt_f16_to_f32)(uint32_t a, CPUState *env)
+{
+    return do_fcvt_f16_to_f32(a, env, &env->vfp.standard_fp_status);
+}
+
+float32 HELPER(neon_fcvt_f32_to_f16)(uint32_t a, CPUState *env)
+{
+    return do_fcvt_f32_to_f16(a, env, &env->vfp.standard_fp_status);
+}
+
+float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, CPUState *env)
+{
+    return do_fcvt_f16_to_f32(a, env, &env->vfp.fp_status);
+}
+
+float32 HELPER(vfp_fcvt_f32_to_f16)(uint32_t a, CPUState *env)
+{
+    return do_fcvt_f32_to_f16(a, env, &env->vfp.fp_status);
+}
+
 float32 HELPER(recps_f32)(float32 a, float32 b, CPUState *env)
 {
     float_status *s = &env->vfp.fp_status;
diff --git a/target-arm/helpers.h b/target-arm/helpers.h
index 8a2564e..40264b4 100644
--- a/target-arm/helpers.h
+++ b/target-arm/helpers.h
@@ -129,6 +129,8 @@ DEF_HELPER_3(vfp_ultod, f64, f64, i32, env)
 
 DEF_HELPER_2(vfp_fcvt_f16_to_f32, f32, i32, env)
 DEF_HELPER_2(vfp_fcvt_f32_to_f16, i32, f32, env)
+DEF_HELPER_2(neon_fcvt_f16_to_f32, f32, i32, env)
+DEF_HELPER_2(neon_fcvt_f32_to_f16, i32, f32, env)
 
 DEF_HELPER_3(recps_f32, f32, f32, f32, env)
 DEF_HELPER_3(rsqrts_f32, f32, f32, f32, env)
diff --git a/target-arm/translate.c b/target-arm/translate.c
index e4649e6..a867f55 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -5495,17 +5495,17 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     tmp = new_tmp();
                     tmp2 = new_tmp();
                     tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
-                    gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
+                    gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
                     tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
-                    gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
+                    gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
                     tcg_gen_shli_i32(tmp2, tmp2, 16);
                     tcg_gen_or_i32(tmp2, tmp2, tmp);
                     tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
-                    gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
+                    gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
                     tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
                     neon_store_reg(rd, 0, tmp2);
                     tmp2 = new_tmp();
-                    gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
+                    gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
                     tcg_gen_shli_i32(tmp2, tmp2, 16);
                     tcg_gen_or_i32(tmp2, tmp2, tmp);
                     neon_store_reg(rd, 1, tmp2);
@@ -5518,17 +5518,17 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     tmp = neon_load_reg(rm, 0);
                     tmp2 = neon_load_reg(rm, 1);
                     tcg_gen_ext16u_i32(tmp3, tmp);
-                    gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
+                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
                     tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
                     tcg_gen_shri_i32(tmp3, tmp, 16);
-                    gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
+                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
                     tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
                     dead_tmp(tmp);
                     tcg_gen_ext16u_i32(tmp3, tmp2);
-                    gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
+                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
                     tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
                     tcg_gen_shri_i32(tmp3, tmp2, 16);
-                    gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
+                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
                     tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
                     dead_tmp(tmp2);
                     dead_tmp(tmp3);
-- 
1.7.1

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

* Re: [Qemu-devel] [PATCH v2 1/6] softfloat: Add float16 type and float16 NaN handling functions
  2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 1/6] softfloat: Add float16 type and float16 NaN handling functions Peter Maydell
@ 2011-02-09 18:40   ` Aurelien Jarno
  2011-02-09 19:25     ` Peter Maydell
  0 siblings, 1 reply; 15+ messages in thread
From: Aurelien Jarno @ 2011-02-09 18:40 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Christophe Lyon, qemu-devel, patches

On Wed, Feb 09, 2011 at 04:27:25PM +0000, Peter Maydell wrote:
> Add a float16 type to softfloat, rather than using bits16 directly.
> Also add the missing functions float16_is_quiet_nan(),
> float16_is_signaling_nan() and float16_maybe_silence_nan(),
> which are needed for the float16 conversion routines.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  fpu/softfloat-specialize.h |   59 ++++++++++++++++++++++++++++++++++++++++++++
>  fpu/softfloat.c            |    8 +++---
>  fpu/softfloat.h            |   12 +++++++-
>  3 files changed, 73 insertions(+), 6 deletions(-)
> 
> diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
> index eb644b2..bc9a66c 100644
> --- a/fpu/softfloat-specialize.h
> +++ b/fpu/softfloat-specialize.h
> @@ -57,6 +57,65 @@ typedef struct {
>  } commonNaNT;
>  
>  /*----------------------------------------------------------------------------
> +| The pattern for a default generated half-precision NaN.
> +*----------------------------------------------------------------------------*/
> +#if defined(TARGET_ARM)
> +#define float16_default_nan 0x7E00
> +#elif SNAN_BIT_IS_ONE
> +#define float16_default_nan 0x7DFF
> +#else
> +#define float16_default_nan 0xFE00
> +#endif
> +
> +/*----------------------------------------------------------------------------
> +| Returns 1 if the half-precision floating-point value `a' is a quiet
> +| NaN; otherwise returns 0.
> +*----------------------------------------------------------------------------*/
> +
> +int float16_is_quiet_nan(float16 a)
> +{
> +#if SNAN_BIT_IS_ONE
> +    return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
> +#else
> +    return ((a & ~0x8000) >= 0x7c80);
> +#endif
> +}
> +
> +/*----------------------------------------------------------------------------
> +| Returns 1 if the half-precision floating-point value `a' is a signaling
> +| NaN; otherwise returns 0.
> +*----------------------------------------------------------------------------*/
> +
> +int float16_is_signaling_nan(float16 a)
> +{
> +#if SNAN_BIT_IS_ONE
> +    return ((a & ~0x8000) >= 0x7c80);
> +#else
> +    return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
> +#endif
> +}
> +
> +/*----------------------------------------------------------------------------
> +| Returns a quiet NaN if the half-precision floating point value `a' is a
> +| signaling NaN; otherwise returns `a'.
> +*----------------------------------------------------------------------------*/
> +float16 float16_maybe_silence_nan(float16 a)
> +{
> +    if (float16_is_signaling_nan(a)) {
> +#if SNAN_BIT_IS_ONE
> +#  if defined(TARGET_MIPS) || defined(TARGET_SH4)
> +        return float16_default_nan;
> +#  else
> +#    error Rules for silencing a signaling NaN are target-specific
> +#  endif
> +#else
> +        a |= (1 << 9);
> +#endif
> +    }
> +    return a;
> +}
> +
> +/*----------------------------------------------------------------------------
>  | The pattern for a default generated single-precision NaN.
>  *----------------------------------------------------------------------------*/
>  #if defined(TARGET_SPARC)
> diff --git a/fpu/softfloat.c b/fpu/softfloat.c
> index 17842f4..dc4492a 100644
> --- a/fpu/softfloat.c
> +++ b/fpu/softfloat.c
> @@ -2713,15 +2713,15 @@ float32 float64_to_float32( float64 a STATUS_PARAM )
>  | than the desired result exponent whenever `zSig' is a complete, normalized
>  | significand.
>  *----------------------------------------------------------------------------*/
> -static bits16 packFloat16(flag zSign, int16 zExp, bits16 zSig)
> +static float16 packFloat16(flag zSign, int16 zExp, bits16 zSig)
>  {
>      return (((bits32)zSign) << 15) + (((bits32)zExp) << 10) + zSig;
>  }
>  
>  /* Half precision floats come in two formats: standard IEEE and "ARM" format.
>     The latter gains extra exponent range by omitting the NaN/Inf encodings.  */
> -  
> -float32 float16_to_float32( bits16 a, flag ieee STATUS_PARAM )
> +
> +float32 float16_to_float32(float16 a, flag ieee STATUS_PARAM)
>  {
>      flag aSign;
>      int16 aExp;
> @@ -2753,7 +2753,7 @@ float32 float16_to_float32( bits16 a, flag ieee STATUS_PARAM )
>      return packFloat32( aSign, aExp + 0x70, aSig << 13);
>  }
>  
> -bits16 float32_to_float16( float32 a, flag ieee STATUS_PARAM)
> +float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM)
>  {
>      flag aSign;
>      int16 aExp;
> diff --git a/fpu/softfloat.h b/fpu/softfloat.h
> index 4a5345c..f773d67 100644
> --- a/fpu/softfloat.h
> +++ b/fpu/softfloat.h
> @@ -118,6 +118,7 @@ enum {
>     sane ABI should be able to see though these structs.  However
>     x86/gcc 3.x seems to struggle a bit, so leave them disabled by default.  */
>  //#define USE_SOFTFLOAT_STRUCT_TYPES
> +typedef uint16_t float16;
>  #ifdef USE_SOFTFLOAT_STRUCT_TYPES
>  typedef struct {
>      uint32_t v;

You should also add it in the USE_SOFTFLOAT_STRUCT_TYPES case, so that
we can check the type correctness. Last time I tried, it was not
compiling in this mode, but it's probably worth having it anyway so that
16-bit floating points values are tested.

> @@ -253,8 +254,15 @@ float128 int64_to_float128( int64_t STATUS_PARAM );
>  /*----------------------------------------------------------------------------
>  | Software half-precision conversion routines.
>  *----------------------------------------------------------------------------*/
> -bits16 float32_to_float16( float32, flag STATUS_PARAM );
> -float32 float16_to_float32( bits16, flag STATUS_PARAM );
> +float16 float32_to_float16( float32, flag STATUS_PARAM );
> +float32 float16_to_float32( float16, flag STATUS_PARAM );
> +
> +/*----------------------------------------------------------------------------
> +| Software half-precision operations.
> +*----------------------------------------------------------------------------*/
> +int float16_is_quiet_nan( float16 );
> +int float16_is_signaling_nan( float16 );
> +float16 float16_maybe_silence_nan( float16 );
>  
>  /*----------------------------------------------------------------------------
>  | Software IEC/IEEE single-precision conversion routines.

Otherwise looks pretty good.


-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 2/6] softfloat: Honour default_nan_mode for float-to-float conversions
  2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 2/6] softfloat: Honour default_nan_mode for float-to-float conversions Peter Maydell
@ 2011-02-09 18:40   ` Aurelien Jarno
  0 siblings, 0 replies; 15+ messages in thread
From: Aurelien Jarno @ 2011-02-09 18:40 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Christophe Lyon, qemu-devel, patches

On Wed, Feb 09, 2011 at 04:27:26PM +0000, Peter Maydell wrote:
> From: Christophe Lyon <christophe.lyon@st.com>
> 
> Honour the default_nan_mode flag when doing conversions between
> different floating point formats, as well as when returning a NaN from
> a two-operand floating point function. This corrects the behaviour
> of float<->double conversions on both ARM and SH4.
> 
> Signed-off-by: Christophe Lyon <christophe.lyon@st.com>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  fpu/softfloat-specialize.h |   29 +++++++++++++++++++++++++----
>  fpu/softfloat.c            |   24 ++++++++++++------------
>  2 files changed, 37 insertions(+), 16 deletions(-)

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

> diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
> index bc9a66c..2f65b9d 100644
> --- a/fpu/softfloat-specialize.h
> +++ b/fpu/softfloat-specialize.h
> @@ -203,9 +203,14 @@ static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )
>  | precision floating-point format.
>  *----------------------------------------------------------------------------*/
>  
> -static float32 commonNaNToFloat32( commonNaNT a )
> +static float32 commonNaNToFloat32( commonNaNT a STATUS_PARAM)
>  {
>      bits32 mantissa = a.high>>41;
> +
> +    if ( STATUS(default_nan_mode) ) {
> +        return float32_default_nan;
> +    }
> +
>      if ( mantissa )
>          return make_float32(
>              ( ( (bits32) a.sign )<<31 ) | 0x7F800000 | ( a.high>>41 ) );
> @@ -457,10 +462,14 @@ static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM)
>  | precision floating-point format.
>  *----------------------------------------------------------------------------*/
>  
> -static float64 commonNaNToFloat64( commonNaNT a )
> +static float64 commonNaNToFloat64( commonNaNT a STATUS_PARAM)
>  {
>      bits64 mantissa = a.high>>12;
>  
> +    if ( STATUS(default_nan_mode) ) {
> +        return float64_default_nan;
> +    }
> +
>      if ( mantissa )
>          return make_float64(
>                ( ( (bits64) a.sign )<<63 )
> @@ -614,10 +623,16 @@ static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM)
>  | double-precision floating-point format.
>  *----------------------------------------------------------------------------*/
>  
> -static floatx80 commonNaNToFloatx80( commonNaNT a )
> +static floatx80 commonNaNToFloatx80( commonNaNT a STATUS_PARAM)
>  {
>      floatx80 z;
>  
> +    if ( STATUS(default_nan_mode) ) {
> +        z.low = floatx80_default_nan_low;
> +        z.high = floatx80_default_nan_high;
> +        return z;
> +    }
> +
>      if (a.high)
>          z.low = a.high;
>      else
> @@ -762,10 +777,16 @@ static commonNaNT float128ToCommonNaN( float128 a STATUS_PARAM)
>  | precision floating-point format.
>  *----------------------------------------------------------------------------*/
>  
> -static float128 commonNaNToFloat128( commonNaNT a )
> +static float128 commonNaNToFloat128( commonNaNT a STATUS_PARAM)
>  {
>      float128 z;
>  
> +    if ( STATUS(default_nan_mode) ) {
> +        z.low = float128_default_nan_low;
> +        z.high = float128_default_nan_high;
> +        return z;
> +    }
> +
>      shift128Right( a.high, a.low, 16, &z.high, &z.low );
>      z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF000000000000 );
>      return z;
> diff --git a/fpu/softfloat.c b/fpu/softfloat.c
> index dc4492a..c3058f4 100644
> --- a/fpu/softfloat.c
> +++ b/fpu/softfloat.c
> @@ -1534,7 +1534,7 @@ float64 float32_to_float64( float32 a STATUS_PARAM )
>      aExp = extractFloat32Exp( a );
>      aSign = extractFloat32Sign( a );
>      if ( aExp == 0xFF ) {
> -        if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a STATUS_VAR ));
> +        if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
>          return packFloat64( aSign, 0x7FF, 0 );
>      }
>      if ( aExp == 0 ) {
> @@ -1566,7 +1566,7 @@ floatx80 float32_to_floatx80( float32 a STATUS_PARAM )
>      aExp = extractFloat32Exp( a );
>      aSign = extractFloat32Sign( a );
>      if ( aExp == 0xFF ) {
> -        if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a STATUS_VAR ) );
> +        if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
>          return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
>      }
>      if ( aExp == 0 ) {
> @@ -1600,7 +1600,7 @@ float128 float32_to_float128( float32 a STATUS_PARAM )
>      aExp = extractFloat32Exp( a );
>      aSign = extractFloat32Sign( a );
>      if ( aExp == 0xFF ) {
> -        if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a STATUS_VAR ) );
> +        if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
>          return packFloat128( aSign, 0x7FFF, 0, 0 );
>      }
>      if ( aExp == 0 ) {
> @@ -2689,7 +2689,7 @@ float32 float64_to_float32( float64 a STATUS_PARAM )
>      aExp = extractFloat64Exp( a );
>      aSign = extractFloat64Sign( a );
>      if ( aExp == 0x7FF ) {
> -        if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a STATUS_VAR ) );
> +        if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
>          return packFloat32( aSign, 0xFF, 0 );
>      }
>      shift64RightJamming( aSig, 22, &aSig );
> @@ -2861,7 +2861,7 @@ floatx80 float64_to_floatx80( float64 a STATUS_PARAM )
>      aExp = extractFloat64Exp( a );
>      aSign = extractFloat64Sign( a );
>      if ( aExp == 0x7FF ) {
> -        if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a STATUS_VAR ) );
> +        if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
>          return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
>      }
>      if ( aExp == 0 ) {
> @@ -2896,7 +2896,7 @@ float128 float64_to_float128( float64 a STATUS_PARAM )
>      aExp = extractFloat64Exp( a );
>      aSign = extractFloat64Sign( a );
>      if ( aExp == 0x7FF ) {
> -        if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a STATUS_VAR ) );
> +        if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
>          return packFloat128( aSign, 0x7FFF, 0, 0 );
>      }
>      if ( aExp == 0 ) {
> @@ -3843,7 +3843,7 @@ float32 floatx80_to_float32( floatx80 a STATUS_PARAM )
>      aSign = extractFloatx80Sign( a );
>      if ( aExp == 0x7FFF ) {
>          if ( (bits64) ( aSig<<1 ) ) {
> -            return commonNaNToFloat32( floatx80ToCommonNaN( a STATUS_VAR ) );
> +            return commonNaNToFloat32( floatx80ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
>          }
>          return packFloat32( aSign, 0xFF, 0 );
>      }
> @@ -3871,7 +3871,7 @@ float64 floatx80_to_float64( floatx80 a STATUS_PARAM )
>      aSign = extractFloatx80Sign( a );
>      if ( aExp == 0x7FFF ) {
>          if ( (bits64) ( aSig<<1 ) ) {
> -            return commonNaNToFloat64( floatx80ToCommonNaN( a STATUS_VAR ) );
> +            return commonNaNToFloat64( floatx80ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
>          }
>          return packFloat64( aSign, 0x7FF, 0 );
>      }
> @@ -3900,7 +3900,7 @@ float128 floatx80_to_float128( floatx80 a STATUS_PARAM )
>      aExp = extractFloatx80Exp( a );
>      aSign = extractFloatx80Sign( a );
>      if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) {
> -        return commonNaNToFloat128( floatx80ToCommonNaN( a STATUS_VAR ) );
> +        return commonNaNToFloat128( floatx80ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
>      }
>      shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 );
>      return packFloat128( aSign, aExp, zSig0, zSig1 );
> @@ -4863,7 +4863,7 @@ float32 float128_to_float32( float128 a STATUS_PARAM )
>      aSign = extractFloat128Sign( a );
>      if ( aExp == 0x7FFF ) {
>          if ( aSig0 | aSig1 ) {
> -            return commonNaNToFloat32( float128ToCommonNaN( a STATUS_VAR ) );
> +            return commonNaNToFloat32( float128ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
>          }
>          return packFloat32( aSign, 0xFF, 0 );
>      }
> @@ -4897,7 +4897,7 @@ float64 float128_to_float64( float128 a STATUS_PARAM )
>      aSign = extractFloat128Sign( a );
>      if ( aExp == 0x7FFF ) {
>          if ( aSig0 | aSig1 ) {
> -            return commonNaNToFloat64( float128ToCommonNaN( a STATUS_VAR ) );
> +            return commonNaNToFloat64( float128ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
>          }
>          return packFloat64( aSign, 0x7FF, 0 );
>      }
> @@ -4932,7 +4932,7 @@ floatx80 float128_to_floatx80( float128 a STATUS_PARAM )
>      aSign = extractFloat128Sign( a );
>      if ( aExp == 0x7FFF ) {
>          if ( aSig0 | aSig1 ) {
> -            return commonNaNToFloatx80( float128ToCommonNaN( a STATUS_VAR ) );
> +            return commonNaNToFloatx80( float128ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
>          }
>          return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
>      }
> -- 
> 1.7.1
> 
> 
> 

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 3/6] softfloat: Fix single-to-half precision float conversions
  2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 3/6] softfloat: Fix single-to-half precision float conversions Peter Maydell
@ 2011-02-09 18:41   ` Aurelien Jarno
  0 siblings, 0 replies; 15+ messages in thread
From: Aurelien Jarno @ 2011-02-09 18:41 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Christophe Lyon, qemu-devel, patches

On Wed, Feb 09, 2011 at 04:27:27PM +0000, Peter Maydell wrote:
> Fix various bugs in the single-to-half-precision conversion code:
>  * input NaNs not correctly converted in IEEE mode
>    (fixed by defining and using a commonNaNToFloat16())
>  * wrong values returned when converting NaN/Inf into non-IEEE
>    half precision value
>  * wrong values returned for conversion of values which are
>    on the boundary between denormal and zero for the half
>    precision format
>  * zeroes not correctly identified
>  * excessively large results in non-IEEE mode should
>    generate InvalidOp, not Overflow
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  fpu/softfloat-specialize.h |   20 ++++++++++++++++++++
>  fpu/softfloat.c            |   30 ++++++++++++++++++------------
>  2 files changed, 38 insertions(+), 12 deletions(-)
> 
> diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
> index 2f65b9d..4907484 100644
> --- a/fpu/softfloat-specialize.h
> +++ b/fpu/softfloat-specialize.h
> @@ -116,6 +116,26 @@ float16 float16_maybe_silence_nan(float16 a)
>  }
>  
>  /*----------------------------------------------------------------------------
> +| Returns the result of converting the canonical NaN `a' to the half-
> +| precision floating-point format.
> +*----------------------------------------------------------------------------*/
> +
> +static float16 commonNaNToFloat16(commonNaNT a STATUS_PARAM)
> +{
> +    uint16_t mantissa = a.high>>54;
> +
> +    if (STATUS(default_nan_mode)) {
> +        return float16_default_nan;
> +    }
> +
> +    if (mantissa) {
> +        return ((((uint16_t) a.sign) << 15) | (0x1F << 10) | mantissa);
> +    } else {
> +        return float16_default_nan;
> +    }
> +}
> +
> +/*----------------------------------------------------------------------------
>  | The pattern for a default generated single-precision NaN.
>  *----------------------------------------------------------------------------*/
>  #if defined(TARGET_SPARC)
> diff --git a/fpu/softfloat.c b/fpu/softfloat.c
> index c3058f4..4d51428 100644
> --- a/fpu/softfloat.c
> +++ b/fpu/softfloat.c
> @@ -2767,25 +2767,31 @@ float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM)
>      aExp = extractFloat32Exp( a );
>      aSign = extractFloat32Sign( a );
>      if ( aExp == 0xFF ) {
> -        if (aSig) {
> -            /* Make sure correct exceptions are raised.  */
> -            float32ToCommonNaN(a STATUS_VAR);
> -            aSig |= 0x00400000;
> +        if ( aSig ) {
> +            /* Input is a NaN */
> +            bits16 r = commonNaNToFloat16( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR );

Here you should now use a float16 instead of bits16.

> +            if (!ieee) {
> +                return packFloat16(aSign, 0, 0);
> +            }
> +            return r;
>          }
> -        return packFloat16(aSign, 0x1f, aSig >> 13);
> +        /* Infinity */
> +        if (!ieee) {
> +            float_raise(float_flag_invalid STATUS_VAR);
> +            return packFloat16(aSign, 0x1f, 0x3ff);
> +        }
> +        return packFloat16(aSign, 0x1f, 0);
>      }
> -    if (aExp == 0 && aSign == 0) {
> +    if (aExp == 0 && aSig == 0) {
>          return packFloat16(aSign, 0, 0);
>      }
>      /* Decimal point between bits 22 and 23.  */
>      aSig |= 0x00800000;
>      aExp -= 0x7f;
>      if (aExp < -14) {
> -        mask = 0x007fffff;
> -        if (aExp < -24) {
> -            aExp = -25;
> -        } else {
> -            mask >>= 24 + aExp;
> +        mask = 0x00ffffff;
> +        if (aExp >= -24) {
> +            mask >>= 25 + aExp;
>          }
>      } else {
>          mask = 0x00001fff;
> @@ -2827,7 +2833,7 @@ float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM)
>          }
>      } else {
>          if (aExp > 16) {
> -            float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR);
> +            float_raise(float_flag_invalid | float_flag_inexact STATUS_VAR);
>              return packFloat16(aSign, 0x1f, 0x3ff);
>          }
>      }

Otherwise looks fine, nice fixes.

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 4/6] softfloat: Correctly handle NaNs in float16_to_float32()
  2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 4/6] softfloat: Correctly handle NaNs in float16_to_float32() Peter Maydell
@ 2011-02-09 18:42   ` Aurelien Jarno
  0 siblings, 0 replies; 15+ messages in thread
From: Aurelien Jarno @ 2011-02-09 18:42 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Christophe Lyon, qemu-devel, patches

On Wed, Feb 09, 2011 at 04:27:28PM +0000, Peter Maydell wrote:
> Correctly handle NaNs in float16_to_float32(), by defining and
> using a float16ToCommonNaN() function, as we do with the other formats.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  fpu/softfloat-specialize.h |   17 +++++++++++++++++
>  fpu/softfloat.c            |    4 +---
>  2 files changed, 18 insertions(+), 3 deletions(-)

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

> diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
> index 4907484..af82359 100644
> --- a/fpu/softfloat-specialize.h
> +++ b/fpu/softfloat-specialize.h
> @@ -116,6 +116,23 @@ float16 float16_maybe_silence_nan(float16 a)
>  }
>  
>  /*----------------------------------------------------------------------------
> +| Returns the result of converting the half-precision floating-point NaN
> +| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
> +| exception is raised.
> +*----------------------------------------------------------------------------*/
> +
> +static commonNaNT float16ToCommonNaN( float16 a STATUS_PARAM )
> +{
> +    commonNaNT z;
> +
> +    if ( float16_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR );
> +    z.sign = a >> 15;
> +    z.low = 0;
> +    z.high = ((bits64) a)<<54;
> +    return z;
> +}
> +
> +/*----------------------------------------------------------------------------
>  | Returns the result of converting the canonical NaN `a' to the half-
>  | precision floating-point format.
>  *----------------------------------------------------------------------------*/
> diff --git a/fpu/softfloat.c b/fpu/softfloat.c
> index 4d51428..735db38 100644
> --- a/fpu/softfloat.c
> +++ b/fpu/softfloat.c
> @@ -2733,9 +2733,7 @@ float32 float16_to_float32(float16 a, flag ieee STATUS_PARAM)
>  
>      if (aExp == 0x1f && ieee) {
>          if (aSig) {
> -            /* Make sure correct exceptions are raised.  */
> -            float32ToCommonNaN(a STATUS_VAR);
> -            aSig |= 0x200;
> +            return commonNaNToFloat32(float16ToCommonNaN(a STATUS_VAR) STATUS_VAR);
>          }
>          return packFloat32(aSign, 0xff, aSig << 13);
>      }
> -- 
> 1.7.1
> 
> 
> 

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 5/6] target-arm: Silence NaNs resulting from half-precision conversions
  2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 5/6] target-arm: Silence NaNs resulting from half-precision conversions Peter Maydell
@ 2011-02-09 18:42   ` Aurelien Jarno
  0 siblings, 0 replies; 15+ messages in thread
From: Aurelien Jarno @ 2011-02-09 18:42 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Christophe Lyon, qemu-devel, patches

On Wed, Feb 09, 2011 at 04:27:29PM +0000, Peter Maydell wrote:
> Silence the NaNs that may result from half-precision conversion,
> as we do for the other conversions.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target-arm/helper.c |   12 ++++++++++--
>  1 files changed, 10 insertions(+), 2 deletions(-)

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index d46defc..503278c 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -2627,14 +2627,22 @@ float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, CPUState *env)
>  {
>      float_status *s = &env->vfp.fp_status;
>      int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
> -    return float16_to_float32(a, ieee, s);
> +    float32 r = float16_to_float32(a, ieee, s);
> +    if (ieee) {
> +        return float32_maybe_silence_nan(r);
> +    }
> +    return r;
>  }
>  
>  uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, CPUState *env)
>  {
>      float_status *s = &env->vfp.fp_status;
>      int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
> -    return float32_to_float16(a, ieee, s);
> +    float16 r = float32_to_float16(a, ieee, s);
> +    if (ieee) {
> +        return float16_maybe_silence_nan(r);
> +    }
> +    return r;
>  }
>  
>  float32 HELPER(recps_f32)(float32 a, float32 b, CPUState *env)
> -- 
> 1.7.1
> 
> 
> 

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 6/6] target-arm: Use standard FPSCR for Neon half-precision operations
  2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 6/6] target-arm: Use standard FPSCR for Neon half-precision operations Peter Maydell
@ 2011-02-09 18:43   ` Aurelien Jarno
  2011-02-09 19:03   ` Peter Maydell
  1 sibling, 0 replies; 15+ messages in thread
From: Aurelien Jarno @ 2011-02-09 18:43 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Christophe Lyon, qemu-devel, patches

On Wed, Feb 09, 2011 at 04:27:30PM +0000, Peter Maydell wrote:
> The Neon half-precision conversion operations (VCVT.F16.F32 and
> VCVT.F32.F16) use ARM standard floating-point arithmetic, unlike
> the VFP versions (VCVTB and VCVTT).
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target-arm/helper.c    |   26 ++++++++++++++++++++++----
>  target-arm/helpers.h   |    2 ++
>  target-arm/translate.c |   16 ++++++++--------
>  3 files changed, 32 insertions(+), 12 deletions(-)

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index 503278c..d36f0f3 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -2623,9 +2623,8 @@ VFP_CONV_FIX(ul, s, float32, uint32, u)
>  #undef VFP_CONV_FIX
>  
>  /* Half precision conversions.  */
> -float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, CPUState *env)
> +static float32 do_fcvt_f16_to_f32(uint32_t a, CPUState *env, float_status *s)
>  {
> -    float_status *s = &env->vfp.fp_status;
>      int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
>      float32 r = float16_to_float32(a, ieee, s);
>      if (ieee) {
> @@ -2634,9 +2633,8 @@ float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, CPUState *env)
>      return r;
>  }
>  
> -uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, CPUState *env)
> +static uint32_t do_fcvt_f32_to_f16(float32 a, CPUState *env, float_status *s)
>  {
> -    float_status *s = &env->vfp.fp_status;
>      int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
>      float16 r = float32_to_float16(a, ieee, s);
>      if (ieee) {
> @@ -2645,6 +2643,26 @@ uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, CPUState *env)
>      return r;
>  }
>  
> +float32 HELPER(neon_fcvt_f16_to_f32)(uint32_t a, CPUState *env)
> +{
> +    return do_fcvt_f16_to_f32(a, env, &env->vfp.standard_fp_status);
> +}
> +
> +float32 HELPER(neon_fcvt_f32_to_f16)(uint32_t a, CPUState *env)
> +{
> +    return do_fcvt_f32_to_f16(a, env, &env->vfp.standard_fp_status);
> +}
> +
> +float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, CPUState *env)
> +{
> +    return do_fcvt_f16_to_f32(a, env, &env->vfp.fp_status);
> +}
> +
> +float32 HELPER(vfp_fcvt_f32_to_f16)(uint32_t a, CPUState *env)
> +{
> +    return do_fcvt_f32_to_f16(a, env, &env->vfp.fp_status);
> +}
> +
>  float32 HELPER(recps_f32)(float32 a, float32 b, CPUState *env)
>  {
>      float_status *s = &env->vfp.fp_status;
> diff --git a/target-arm/helpers.h b/target-arm/helpers.h
> index 8a2564e..40264b4 100644
> --- a/target-arm/helpers.h
> +++ b/target-arm/helpers.h
> @@ -129,6 +129,8 @@ DEF_HELPER_3(vfp_ultod, f64, f64, i32, env)
>  
>  DEF_HELPER_2(vfp_fcvt_f16_to_f32, f32, i32, env)
>  DEF_HELPER_2(vfp_fcvt_f32_to_f16, i32, f32, env)
> +DEF_HELPER_2(neon_fcvt_f16_to_f32, f32, i32, env)
> +DEF_HELPER_2(neon_fcvt_f32_to_f16, i32, f32, env)
>  
>  DEF_HELPER_3(recps_f32, f32, f32, f32, env)
>  DEF_HELPER_3(rsqrts_f32, f32, f32, f32, env)
> diff --git a/target-arm/translate.c b/target-arm/translate.c
> index e4649e6..a867f55 100644
> --- a/target-arm/translate.c
> +++ b/target-arm/translate.c
> @@ -5495,17 +5495,17 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
>                      tmp = new_tmp();
>                      tmp2 = new_tmp();
>                      tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
> -                    gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
> +                    gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
>                      tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
> -                    gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
> +                    gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
>                      tcg_gen_shli_i32(tmp2, tmp2, 16);
>                      tcg_gen_or_i32(tmp2, tmp2, tmp);
>                      tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
> -                    gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
> +                    gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
>                      tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
>                      neon_store_reg(rd, 0, tmp2);
>                      tmp2 = new_tmp();
> -                    gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
> +                    gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
>                      tcg_gen_shli_i32(tmp2, tmp2, 16);
>                      tcg_gen_or_i32(tmp2, tmp2, tmp);
>                      neon_store_reg(rd, 1, tmp2);
> @@ -5518,17 +5518,17 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
>                      tmp = neon_load_reg(rm, 0);
>                      tmp2 = neon_load_reg(rm, 1);
>                      tcg_gen_ext16u_i32(tmp3, tmp);
> -                    gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
> +                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
>                      tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
>                      tcg_gen_shri_i32(tmp3, tmp, 16);
> -                    gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
> +                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
>                      tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
>                      dead_tmp(tmp);
>                      tcg_gen_ext16u_i32(tmp3, tmp2);
> -                    gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
> +                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
>                      tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
>                      tcg_gen_shri_i32(tmp3, tmp2, 16);
> -                    gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
> +                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
>                      tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
>                      dead_tmp(tmp2);
>                      dead_tmp(tmp3);
> -- 
> 1.7.1
> 
> 
> 

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 6/6] target-arm: Use standard FPSCR for Neon half-precision operations
  2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 6/6] target-arm: Use standard FPSCR for Neon half-precision operations Peter Maydell
  2011-02-09 18:43   ` Aurelien Jarno
@ 2011-02-09 19:03   ` Peter Maydell
  1 sibling, 0 replies; 15+ messages in thread
From: Peter Maydell @ 2011-02-09 19:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: Christophe Lyon, Aurelien Jarno, patches

On 9 February 2011 16:27, Peter Maydell <peter.maydell@linaro.org> wrote:
> -uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, CPUState *env)
> +static uint32_t do_fcvt_f32_to_f16(float32 a, CPUState *env, float_status *s)


> +float32 HELPER(neon_fcvt_f32_to_f16)(uint32_t a, CPUState *env)

> +float32 HELPER(vfp_fcvt_f32_to_f16)(uint32_t a, CPUState *env)

Just noticed this accidental change due to cut-n-paste error, the _to_f16
helpers should still be returning uint32_t, not float32.

-- PMM

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

* Re: [Qemu-devel] [PATCH v2 1/6] softfloat: Add float16 type and float16 NaN handling functions
  2011-02-09 18:40   ` Aurelien Jarno
@ 2011-02-09 19:25     ` Peter Maydell
  0 siblings, 0 replies; 15+ messages in thread
From: Peter Maydell @ 2011-02-09 19:25 UTC (permalink / raw)
  To: Aurelien Jarno; +Cc: Christophe Lyon, qemu-devel, patches

On 9 February 2011 18:40, Aurelien Jarno <aurelien@aurel32.net> wrote:
> You should also add it in the USE_SOFTFLOAT_STRUCT_TYPES case, so that
> we can check the type correctness. Last time I tried, it was not
> compiling in this mode

Yeah, it doesn't compile, but it's not too hard to fix (at least for ARM
targets). It looks like we need a new macro:
#ifdef USE_SOFTFLOAT_STRUCT_TYPES
#define const_float32(x) { x }
#else
#define const_float32(x) x
#endif

so you can define arrays of float32 etc:
static const float32 my_array[] = {
    const_float32(0x00000000),				/* single 0.0 */
    const_float32(0x3f800000),				/* single 1.0 */
 };

as there are a couple of places that do this and complain otherwise.

...unless anybody can come up with a cleverer fix.

-- PMM

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

end of thread, other threads:[~2011-02-09 19:25 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-02-09 16:27 [Qemu-devel] [PATCH v2 0/6] target-arm: Fix floating point conversions Peter Maydell
2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 1/6] softfloat: Add float16 type and float16 NaN handling functions Peter Maydell
2011-02-09 18:40   ` Aurelien Jarno
2011-02-09 19:25     ` Peter Maydell
2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 2/6] softfloat: Honour default_nan_mode for float-to-float conversions Peter Maydell
2011-02-09 18:40   ` Aurelien Jarno
2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 3/6] softfloat: Fix single-to-half precision float conversions Peter Maydell
2011-02-09 18:41   ` Aurelien Jarno
2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 4/6] softfloat: Correctly handle NaNs in float16_to_float32() Peter Maydell
2011-02-09 18:42   ` Aurelien Jarno
2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 5/6] target-arm: Silence NaNs resulting from half-precision conversions Peter Maydell
2011-02-09 18:42   ` Aurelien Jarno
2011-02-09 16:27 ` [Qemu-devel] [PATCH v2 6/6] target-arm: Use standard FPSCR for Neon half-precision operations Peter Maydell
2011-02-09 18:43   ` Aurelien Jarno
2011-02-09 19:03   ` Peter Maydell

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