qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v2] fpu: add mechanism to check for invalid long dou


From: Andrew Dutcher
Subject: [Qemu-devel] [PATCH v2] fpu: add mechanism to check for invalid long double formats
Date: Sat, 13 Aug 2016 17:33:08 -0700

The macro require_valid_floatx80(value, status) will check for malformed
extended precision encodings, and if one is found, generate an
invalid-operation exception and return NaN. This check has been added to
the beginning of the basic 80-bit float arithmetic functions.

Version 2: fix code style

Signed-off-by: Andrew Dutcher <address@hidden>
---
 fpu/softfloat-specialize.h | 12 ++++++++++++
 fpu/softfloat.c            | 11 +++++++++++
 include/fpu/softfloat.h    | 13 +++++++++++++
 3 files changed, 36 insertions(+)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 43d0890..0e6ec25 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -203,6 +203,18 @@ void float_raise(int8_t flags, float_status *status)
 }
 
 /*----------------------------------------------------------------------------
+| Asserts that the given value must be a valid floatx80 encoding. If The given
+| value is a pseudo-NaN, pseudo-infiinty, or un-normal, raise an invalid
+| operation exception and cause the parent function to return NaN.
+*----------------------------------------------------------------------------*/
+
+#define require_valid_floatx80(a, status)           \
+    if (floatx80_invalid_encoding((a))) {               \
+        float_raise(float_flag_invalid, (status));        \
+        return floatx80_default_nan((status));            \
+    }
+
+/*----------------------------------------------------------------------------
 | Internal canonical NaN format.
 *----------------------------------------------------------------------------*/
 typedef struct {
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 9b1eccf..a921e5e 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -5279,6 +5279,8 @@ floatx80 floatx80_add(floatx80 a, floatx80 b, 
float_status *status)
 {
     flag aSign, bSign;
 
+    require_valid_floatx80(a, status);
+    require_valid_floatx80(b, status);
     aSign = extractFloatx80Sign( a );
     bSign = extractFloatx80Sign( b );
     if ( aSign == bSign ) {
@@ -5300,6 +5302,8 @@ floatx80 floatx80_sub(floatx80 a, floatx80 b, 
float_status *status)
 {
     flag aSign, bSign;
 
+    require_valid_floatx80(a, status);
+    require_valid_floatx80(b, status);
     aSign = extractFloatx80Sign( a );
     bSign = extractFloatx80Sign( b );
     if ( aSign == bSign ) {
@@ -5323,6 +5327,8 @@ floatx80 floatx80_mul(floatx80 a, floatx80 b, 
float_status *status)
     int32_t aExp, bExp, zExp;
     uint64_t aSig, bSig, zSig0, zSig1;
 
+    require_valid_floatx80(a, status);
+    require_valid_floatx80(b, status);
     aSig = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
     aSign = extractFloatx80Sign( a );
@@ -5380,6 +5386,8 @@ floatx80 floatx80_div(floatx80 a, floatx80 b, 
float_status *status)
     uint64_t aSig, bSig, zSig0, zSig1;
     uint64_t rem0, rem1, rem2, term0, term1, term2;
 
+    require_valid_floatx80(a, status);
+    require_valid_floatx80(b, status);
     aSig = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
     aSign = extractFloatx80Sign( a );
@@ -5461,6 +5469,8 @@ floatx80 floatx80_rem(floatx80 a, floatx80 b, 
float_status *status)
     uint64_t aSig0, aSig1, bSig;
     uint64_t q, term0, term1, alternateASig0, alternateASig1;
 
+    require_valid_floatx80(a, status);
+    require_valid_floatx80(b, status);
     aSig0 = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
     aSign = extractFloatx80Sign( a );
@@ -5556,6 +5566,7 @@ floatx80 floatx80_sqrt(floatx80 a, float_status *status)
     uint64_t aSig0, aSig1, zSig0, zSig1, doubleZSig0;
     uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3;
 
+    require_valid_floatx80(a, status);
     aSig0 = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
     aSign = extractFloatx80Sign( a );
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 0e57ee5..569730f 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -671,6 +671,19 @@ static inline int floatx80_is_any_nan(floatx80 a)
 floatx80 floatx80_default_nan(float_status *status);
 
 /*----------------------------------------------------------------------------
+| Return whether the given value is an invalid floatx80 encoding.
+| Invalid floatx80 encodings arise when the integer bit is not set, but
+| the exponent is not zero. The only times the integer bit is permitted to
+| be zero is in subnormal numbers and the value zero.
+*----------------------------------------------------------------------------*/
+
+static inline bool floatx80_invalid_encoding(floatx80 a)
+{
+    return !(a.low & 0x8000000000000000) && !!(a.high & 0x7FFF);
+}
+
+
+/*----------------------------------------------------------------------------
 | Software IEC/IEEE quadruple-precision conversion routines.
 *----------------------------------------------------------------------------*/
 int32_t float128_to_int32(float128, float_status *status);
-- 
2.7.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]