[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] fpu: add mechanism to check for invalid long double
From: |
Andrew Dutcher |
Subject: |
[Qemu-devel] [PATCH] fpu: add mechanism to check for invalid long double formats |
Date: |
Fri, 12 Aug 2016 20:33:05 -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.
Signed-off-by: Andrew Dutcher <address@hidden>
---
fpu/softfloat-specialize.h | 12 ++++++++++++
fpu/softfloat.c | 11 +++++++++++
include/fpu/softfloat.h | 12 ++++++++++++
3 files changed, 35 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..cf703ef 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -671,6 +671,18 @@ 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
- [Qemu-devel] [PATCH] fpu: add mechanism to check for invalid long double formats,
Andrew Dutcher <=