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