Merge pull request #620 from rhelmot/feat/invalid_floatx80_check

Port patch from upstream to check for invalid long double encodings
This commit is contained in:
Nguyen Anh Quynh 2016-08-21 09:48:26 +08:00 committed by GitHub
commit 8e1102f741
2 changed files with 116 additions and 17 deletions

View File

@ -4602,6 +4602,10 @@ int32 floatx80_to_int32( floatx80 a STATUS_PARAM )
int32 aExp, shiftCount;
uint64_t aSig;
if (floatx80_invalid_encoding(a)) {
float_raise(float_flag_invalid STATUS_VAR);
return 1 << 31;
}
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
@ -4630,6 +4634,10 @@ int32 floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM )
uint64_t aSig, savedASig;
int32_t z;
if (floatx80_invalid_encoding(a)) {
float_raise(float_flag_invalid STATUS_VAR);
return 1 << 31;
}
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
@ -4674,6 +4682,10 @@ int64 floatx80_to_int64( floatx80 a STATUS_PARAM )
int32 aExp, shiftCount;
uint64_t aSig, aSigExtra;
if (floatx80_invalid_encoding(a)) {
float_raise(float_flag_invalid STATUS_VAR);
return (uint64_t)1 << 63;
}
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
@ -4715,6 +4727,10 @@ int64 floatx80_to_int64_round_to_zero( floatx80 a STATUS_PARAM )
uint64_t aSig;
int64 z;
if (floatx80_invalid_encoding(a)) {
float_raise(float_flag_invalid STATUS_VAR);
return (uint64_t)1 << 63;
}
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
@ -4755,6 +4771,10 @@ float32 floatx80_to_float32( floatx80 a STATUS_PARAM )
int32 aExp;
uint64_t aSig;
if (floatx80_invalid_encoding(a)) {
float_raise(float_flag_invalid STATUS_VAR);
return float32_default_nan;
}
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
@ -4783,6 +4803,10 @@ float64 floatx80_to_float64( floatx80 a STATUS_PARAM )
int32 aExp;
uint64_t aSig, zSig;
if (floatx80_invalid_encoding(a)) {
float_raise(float_flag_invalid STATUS_VAR);
return float64_default_nan;
}
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
@ -4811,6 +4835,10 @@ float128 floatx80_to_float128( floatx80 a STATUS_PARAM )
int_fast16_t aExp;
uint64_t aSig, zSig0, zSig1;
if (floatx80_invalid_encoding(a)) {
float_raise(float_flag_invalid STATUS_VAR);
return float128_default_nan;
}
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
@ -4836,6 +4864,10 @@ floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM )
uint64_t lastBitMask, roundBitsMask;
floatx80 z;
if (floatx80_invalid_encoding(a)) {
float_raise(float_flag_invalid STATUS_VAR);
return floatx80_default_nan;
}
aExp = extractFloatx80Exp( a );
if ( 0x403E <= aExp ) {
if ( ( aExp == 0x7FFF ) && (uint64_t) ( extractFloatx80Frac( a )<<1 ) ) {
@ -5058,6 +5090,10 @@ floatx80 floatx80_add( floatx80 a, floatx80 b STATUS_PARAM )
{
flag aSign, bSign;
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
float_raise(float_flag_invalid STATUS_VAR);
return floatx80_default_nan;
}
aSign = extractFloatx80Sign( a );
bSign = extractFloatx80Sign( b );
if ( aSign == bSign ) {
@ -5079,6 +5115,10 @@ floatx80 floatx80_sub( floatx80 a, floatx80 b STATUS_PARAM )
{
flag aSign, bSign;
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
float_raise(float_flag_invalid STATUS_VAR);
return floatx80_default_nan;
}
aSign = extractFloatx80Sign( a );
bSign = extractFloatx80Sign( b );
if ( aSign == bSign ) {
@ -5103,6 +5143,10 @@ floatx80 floatx80_mul( floatx80 a, floatx80 b STATUS_PARAM )
uint64_t aSig, bSig, zSig0, zSig1;
floatx80 z;
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
float_raise(float_flag_invalid STATUS_VAR);
return floatx80_default_nan;
}
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
@ -5163,6 +5207,10 @@ floatx80 floatx80_div( floatx80 a, floatx80 b STATUS_PARAM )
uint64_t rem0, rem1, rem2, term0, term1, term2;
floatx80 z;
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
float_raise(float_flag_invalid STATUS_VAR);
return floatx80_default_nan;
}
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
@ -5243,6 +5291,10 @@ floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM )
uint64_t q, term0, term1, alternateASig0, alternateASig1;
floatx80 z;
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
float_raise(float_flag_invalid STATUS_VAR);
return floatx80_default_nan;
}
aSig0 = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
@ -5339,6 +5391,10 @@ floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM )
uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3;
floatx80 z;
if (floatx80_invalid_encoding(a)) {
float_raise(float_flag_invalid STATUS_VAR);
return floatx80_default_nan;
}
aSig0 = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
@ -5405,10 +5461,11 @@ floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM )
int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM )
{
if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
|| ( ( extractFloatx80Exp( b ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)
|| (extractFloatx80Exp(a) == 0x7FFF
&& (uint64_t) (extractFloatx80Frac(a) << 1))
|| (extractFloatx80Exp(b) == 0x7FFF
&& (uint64_t) (extractFloatx80Frac(b) << 1))
) {
float_raise( float_flag_invalid STATUS_VAR);
return 0;
@ -5434,10 +5491,11 @@ int floatx80_le( floatx80 a, floatx80 b STATUS_PARAM )
{
flag aSign, bSign;
if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
|| ( ( extractFloatx80Exp( b ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)
|| (extractFloatx80Exp(a) == 0x7FFF
&& (uint64_t) (extractFloatx80Frac(a) << 1))
|| (extractFloatx80Exp(b) == 0x7FFF
&& (uint64_t) (extractFloatx80Frac(b) << 1))
) {
float_raise( float_flag_invalid STATUS_VAR);
return 0;
@ -5467,10 +5525,11 @@ int floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM )
{
flag aSign, bSign;
if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
|| ( ( extractFloatx80Exp( b ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)
|| (extractFloatx80Exp(a) == 0x7FFF
&& (uint64_t) (extractFloatx80Frac(a) << 1))
|| (extractFloatx80Exp(b) == 0x7FFF
&& (uint64_t) (extractFloatx80Frac(b) << 1))
) {
float_raise( float_flag_invalid STATUS_VAR);
return 0;
@ -5497,10 +5556,11 @@ int floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM )
*----------------------------------------------------------------------------*/
int floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM )
{
if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
|| ( ( extractFloatx80Exp( b ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)
|| (extractFloatx80Exp(a) == 0x7FFF
&& (uint64_t) (extractFloatx80Frac(a) << 1))
|| (extractFloatx80Exp(b) == 0x7FFF
&& (uint64_t) (extractFloatx80Frac(b) << 1))
) {
float_raise( float_flag_invalid STATUS_VAR);
return 1;
@ -5518,6 +5578,10 @@ int floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM )
int floatx80_eq_quiet( floatx80 a, floatx80 b STATUS_PARAM )
{
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
float_raise(float_flag_invalid STATUS_VAR);
return 0;
}
if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
|| ( ( extractFloatx80Exp( b ) == 0x7FFF )
@ -5549,6 +5613,10 @@ int floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM )
{
flag aSign, bSign;
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
float_raise(float_flag_invalid STATUS_VAR);
return 0;
}
if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
|| ( ( extractFloatx80Exp( b ) == 0x7FFF )
@ -5585,6 +5653,10 @@ int floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM )
{
flag aSign, bSign;
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
float_raise(float_flag_invalid STATUS_VAR);
return 0;
}
if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
|| ( ( extractFloatx80Exp( b ) == 0x7FFF )
@ -5618,6 +5690,10 @@ int floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM )
*----------------------------------------------------------------------------*/
int floatx80_unordered_quiet( floatx80 a, floatx80 b STATUS_PARAM )
{
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
float_raise(float_flag_invalid STATUS_VAR);
return 1;
}
if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
|| ( ( extractFloatx80Exp( b ) == 0x7FFF )
@ -6855,7 +6931,7 @@ uint32 float32_to_uint32( float32 a STATUS_PARAM )
} else {
return v;
}
set_float_exception_flags(old_exc_flags, status);
set_float_exception_flags(old_exc_flags STATUS_VAR);
float_raise(float_flag_invalid STATUS_VAR);
return res;
}
@ -7145,6 +7221,10 @@ static inline int floatx80_compare_internal( floatx80 a, floatx80 b,
{
flag aSign, bSign;
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
float_raise(float_flag_invalid STATUS_VAR);
return float_relation_unordered;
}
if (( ( extractFloatx80Exp( a ) == 0x7fff ) &&
( extractFloatx80Frac( a )<<1 ) ) ||
( ( extractFloatx80Exp( b ) == 0x7fff ) &&
@ -7409,6 +7489,10 @@ floatx80 floatx80_scalbn( floatx80 a, int n STATUS_PARAM )
int32_t aExp;
uint64_t aSig;
if (floatx80_invalid_encoding(a)) {
float_raise(float_flag_invalid STATUS_VAR);
return floatx80_default_nan;
}
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );

View File

@ -625,6 +625,21 @@ static inline int floatx80_is_any_nan(floatx80 a)
return ((a.high & 0x7fff) == 0x7fff) && (a.low<<1);
}
/*----------------------------------------------------------------------------
| 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.
| This includes what the Intel software developer's manual calls pseudo-NaNs,
| pseudo-infinities and un-normal numbers. It does not include
| pseudo-denormals, which must still be correctly handled as inputs even
| if they are never generated as outputs.
*----------------------------------------------------------------------------*/
static inline bool floatx80_invalid_encoding(floatx80 a)
{
return (a.low & ((uint64_t)1 << 63)) == 0 && (a.high & 0x7FFF) != 0;
}
#define floatx80_zero make_floatx80(0x0000, 0x0000000000000000LL)
#define floatx80_one make_floatx80(0x3fff, 0x8000000000000000LL)
#define floatx80_ln2 make_floatx80(0x3ffe, 0xb17217f7d1cf79acLL)