From f7e81a945737631c19405a39d510d2284257c3ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Mon, 12 Aug 2019 16:04:02 +0100 Subject: fpu: replace LIT64 usage with UINT64_C for specialize constants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have a wrapper that does the right thing from stdint.h so lets use it for our constants in softfloat-specialize.h Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson --- fpu/softfloat-specialize.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h index 7b88957..5ab2fa1 100644 --- a/fpu/softfloat-specialize.h +++ b/fpu/softfloat-specialize.h @@ -196,11 +196,11 @@ floatx80 floatx80_default_nan(float_status *status) /* None of the targets that have snan_bit_is_one use floatx80. */ assert(!snan_bit_is_one(status)); #if defined(TARGET_M68K) - r.low = LIT64(0xFFFFFFFFFFFFFFFF); + r.low = UINT64_C(0xFFFFFFFFFFFFFFFF); r.high = 0x7FFF; #else /* X86 */ - r.low = LIT64(0xC000000000000000); + r.low = UINT64_C(0xC000000000000000); r.high = 0xFFFF; #endif return r; @@ -212,9 +212,9 @@ floatx80 floatx80_default_nan(float_status *status) #define floatx80_infinity_high 0x7FFF #if defined(TARGET_M68K) -#define floatx80_infinity_low LIT64(0x0000000000000000) +#define floatx80_infinity_low UINT64_C(0x0000000000000000) #else -#define floatx80_infinity_low LIT64(0x8000000000000000) +#define floatx80_infinity_low UINT64_C(0x8000000000000000) #endif const floatx80 floatx80_infinity @@ -667,7 +667,7 @@ int float64_is_signaling_nan(float64 a_, float_status *status) return ((a << 1) >= 0xFFF0000000000000ULL); } else { return (((a >> 51) & 0xFFF) == 0xFFE) - && (a & LIT64(0x0007FFFFFFFFFFFF)); + && (a & UINT64_C(0x0007FFFFFFFFFFFF)); } #endif } @@ -707,7 +707,7 @@ static float64 commonNaNToFloat64(commonNaNT a, float_status *status) if (mantissa) { return make_float64( (((uint64_t) a.sign) << 63) - | LIT64(0x7FF0000000000000) + | UINT64_C(0x7FF0000000000000) | (a.high >> 12)); } else { return float64_default_nan(status); @@ -790,7 +790,7 @@ int floatx80_is_quiet_nan(floatx80 a, float_status *status) && (a.low == aLow); } else { return ((a.high & 0x7FFF) == 0x7FFF) - && (LIT64(0x8000000000000000) <= ((uint64_t)(a.low << 1))); + && (UINT64_C(0x8000000000000000) <= ((uint64_t)(a.low << 1))); } #endif } @@ -812,7 +812,7 @@ int floatx80_is_signaling_nan(floatx80 a, float_status *status) } else { uint64_t aLow; - aLow = a.low & ~LIT64(0x4000000000000000); + aLow = a.low & ~UINT64_C(0x4000000000000000); return ((a.high & 0x7FFF) == 0x7FFF) && (uint64_t)(aLow << 1) && (a.low == aLow); @@ -829,7 +829,7 @@ floatx80 floatx80_silence_nan(floatx80 a, float_status *status) { /* None of the targets that have snan_bit_is_one use floatx80. */ assert(!snan_bit_is_one(status)); - a.low |= LIT64(0xC000000000000000); + a.low |= UINT64_C(0xC000000000000000); return a; } @@ -874,7 +874,7 @@ static floatx80 commonNaNToFloatx80(commonNaNT a, float_status *status) } if (a.high >> 1) { - z.low = LIT64(0x8000000000000000) | a.high >> 1; + z.low = UINT64_C(0x8000000000000000) | a.high >> 1; z.high = (((uint16_t)a.sign) << 15) | 0x7FFF; } else { z = floatx80_default_nan(status); @@ -969,7 +969,7 @@ int float128_is_signaling_nan(float128 a, float_status *status) && (a.low || (a.high & 0x0000FFFFFFFFFFFFULL)); } else { return (((a.high >> 47) & 0xFFFF) == 0xFFFE) - && (a.low || (a.high & LIT64(0x00007FFFFFFFFFFF))); + && (a.low || (a.high & UINT64_C(0x00007FFFFFFFFFFF))); } #endif } @@ -987,7 +987,7 @@ float128 float128_silence_nan(float128 a, float_status *status) if (snan_bit_is_one(status)) { return float128_default_nan(status); } else { - a.high |= LIT64(0x0000800000000000); + a.high |= UINT64_C(0x0000800000000000); return a; } #endif @@ -1025,7 +1025,7 @@ static float128 commonNaNToFloat128(commonNaNT a, float_status *status) } shift128Right(a.high, a.low, 16, &z.high, &z.low); - z.high |= (((uint64_t)a.sign) << 63) | LIT64(0x7FFF000000000000); + z.high |= (((uint64_t)a.sign) << 63) | UINT64_C(0x7FFF000000000000); return z; } -- cgit v1.1 From e6b405fe00d8e6424a58492b37a1656d1ef0929b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Mon, 12 Aug 2019 17:19:33 +0100 Subject: fpu: convert float[16/32/64]_squash_denormal to new modern style MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This also allows us to remove the extractFloat16exp/frac helpers. We avoid using the floatXX_pack_raw functions as they are slight overkill for masking out all but the top bit of the number. The generated code is almost exactly the same as makes no difference to the pre-conversion code. Signed-off-by: Alex Bennée --- fpu/softfloat.c | 112 +++++++++++++++++++++++++------------------------------- 1 file changed, 49 insertions(+), 63 deletions(-) diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 2ba36ec..5385589 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -415,24 +415,6 @@ float64_gen2(float64 xa, float64 xb, float_status *s, } /*---------------------------------------------------------------------------- -| Returns the fraction bits of the half-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -static inline uint32_t extractFloat16Frac(float16 a) -{ - return float16_val(a) & 0x3ff; -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the half-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -static inline int extractFloat16Exp(float16 a) -{ - return (float16_val(a) >> 10) & 0x1f; -} - -/*---------------------------------------------------------------------------- | Returns the fraction bits of the single-precision floating-point value `a'. *----------------------------------------------------------------------------*/ @@ -3306,6 +3288,55 @@ float64 float64_silence_nan(float64 a, float_status *status) return float64_pack_raw(p); } + +/*---------------------------------------------------------------------------- +| If `a' is denormal and we are in flush-to-zero mode then set the +| input-denormal exception and return zero. Otherwise just return the value. +*----------------------------------------------------------------------------*/ + +static bool parts_squash_denormal(FloatParts p, float_status *status) +{ + if (p.exp == 0 && p.frac != 0) { + float_raise(float_flag_input_denormal, status); + return true; + } + + return false; +} + +float16 float16_squash_input_denormal(float16 a, float_status *status) +{ + if (status->flush_inputs_to_zero) { + FloatParts p = float16_unpack_raw(a); + if (parts_squash_denormal(p, status)) { + return float16_set_sign(float16_zero, p.sign); + } + } + return a; +} + +float32 float32_squash_input_denormal(float32 a, float_status *status) +{ + if (status->flush_inputs_to_zero) { + FloatParts p = float32_unpack_raw(a); + if (parts_squash_denormal(p, status)) { + return float32_set_sign(float32_zero, p.sign); + } + } + return a; +} + +float64 float64_squash_input_denormal(float64 a, float_status *status) +{ + if (status->flush_inputs_to_zero) { + FloatParts p = float64_unpack_raw(a); + if (parts_squash_denormal(p, status)) { + return float64_set_sign(float64_zero, p.sign); + } + } + return a; +} + /*---------------------------------------------------------------------------- | Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 | and 7, and returns the properly rounded 32-bit integer corresponding to the @@ -3483,21 +3514,6 @@ static int64_t roundAndPackUint64(flag zSign, uint64_t absZ0, } /*---------------------------------------------------------------------------- -| If `a' is denormal and we are in flush-to-zero mode then set the -| input-denormal exception and return zero. Otherwise just return the value. -*----------------------------------------------------------------------------*/ -float32 float32_squash_input_denormal(float32 a, float_status *status) -{ - if (status->flush_inputs_to_zero) { - if (extractFloat32Exp(a) == 0 && extractFloat32Frac(a) != 0) { - float_raise(float_flag_input_denormal, status); - return make_float32(float32_val(a) & 0x80000000); - } - } - return a; -} - -/*---------------------------------------------------------------------------- | Normalizes the subnormal single-precision floating-point value represented | by the denormalized significand `aSig'. The normalized exponent and | significand are stored at the locations pointed to by `zExpPtr' and @@ -3636,21 +3652,6 @@ static float32 } /*---------------------------------------------------------------------------- -| If `a' is denormal and we are in flush-to-zero mode then set the -| input-denormal exception and return zero. Otherwise just return the value. -*----------------------------------------------------------------------------*/ -float64 float64_squash_input_denormal(float64 a, float_status *status) -{ - if (status->flush_inputs_to_zero) { - if (extractFloat64Exp(a) == 0 && extractFloat64Frac(a) != 0) { - float_raise(float_flag_input_denormal, status); - return make_float64(float64_val(a) & (1ULL << 63)); - } - } - return a; -} - -/*---------------------------------------------------------------------------- | Normalizes the subnormal double-precision floating-point value represented | by the denormalized significand `aSig'. The normalized exponent and | significand are stored at the locations pointed to by `zExpPtr' and @@ -4982,21 +4983,6 @@ int float32_unordered_quiet(float32 a, float32 b, float_status *status) } /*---------------------------------------------------------------------------- -| If `a' is denormal and we are in flush-to-zero mode then set the -| input-denormal exception and return zero. Otherwise just return the value. -*----------------------------------------------------------------------------*/ -float16 float16_squash_input_denormal(float16 a, float_status *status) -{ - if (status->flush_inputs_to_zero) { - if (extractFloat16Exp(a) == 0 && extractFloat16Frac(a) != 0) { - float_raise(float_flag_input_denormal, status); - return make_float16(float16_val(a) & 0x8000); - } - } - return a; -} - -/*---------------------------------------------------------------------------- | Returns the result of converting the double-precision floating-point value | `a' to the extended double-precision floating-point format. The conversion | is performed according to the IEC/IEEE Standard for Binary Floating-Point -- cgit v1.1 From 2c217da0fc9f1127bda804e2a500b8138b02c581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 13 Aug 2019 11:55:32 +0100 Subject: fpu: use min/max values from stdint.h for integral overflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove some more use of LIT64 while making the meaning more clear. We also avoid the need of casts as the results by definition fit into the return type. Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson --- fpu/softfloat.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 5385589..d2cdf4a 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -3384,7 +3384,7 @@ static int32_t roundAndPackInt32(flag zSign, uint64_t absZ, float_status *status if ( zSign ) z = - z; if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) { float_raise(float_flag_invalid, status); - return zSign ? (int32_t) 0x80000000 : 0x7FFFFFFF; + return zSign ? INT32_MIN : INT32_MAX; } if (roundBits) { status->float_exception_flags |= float_flag_inexact; @@ -3444,9 +3444,7 @@ static int64_t roundAndPackInt64(flag zSign, uint64_t absZ0, uint64_t absZ1, if ( z && ( ( z < 0 ) ^ zSign ) ) { overflow: float_raise(float_flag_invalid, status); - return - zSign ? (int64_t) LIT64( 0x8000000000000000 ) - : LIT64( 0x7FFFFFFFFFFFFFFF ); + return zSign ? INT64_MIN : INT64_MAX; } if (absZ1) { status->float_exception_flags |= float_flag_inexact; @@ -3497,7 +3495,7 @@ static int64_t roundAndPackUint64(flag zSign, uint64_t absZ0, ++absZ0; if (absZ0 == 0) { float_raise(float_flag_invalid, status); - return LIT64(0xFFFFFFFFFFFFFFFF); + return UINT64_MAX; } absZ0 &= ~(((uint64_t)(absZ1<<1) == 0) & roundNearestEven); } @@ -5518,9 +5516,9 @@ int64_t floatx80_to_int64(floatx80 a, float_status *status) if ( shiftCount ) { float_raise(float_flag_invalid, status); if (!aSign || floatx80_is_any_nan(a)) { - return LIT64( 0x7FFFFFFFFFFFFFFF ); + return INT64_MAX; } - return (int64_t) LIT64( 0x8000000000000000 ); + return INT64_MIN; } aSigExtra = 0; } @@ -5561,10 +5559,10 @@ int64_t floatx80_to_int64_round_to_zero(floatx80 a, float_status *status) if ( ( a.high != 0xC03E ) || aSig ) { float_raise(float_flag_invalid, status); if ( ! aSign || ( ( aExp == 0x7FFF ) && aSig ) ) { - return LIT64( 0x7FFFFFFFFFFFFFFF ); + return INT64_MAX; } } - return (int64_t) LIT64( 0x8000000000000000 ); + return INT64_MIN; } else if ( aExp < 0x3FFF ) { if (aExp | aSig) { @@ -6623,7 +6621,7 @@ int32_t float128_to_int32_round_to_zero(float128 a, float_status *status) if ( ( z < 0 ) ^ aSign ) { invalid: float_raise(float_flag_invalid, status); - return aSign ? (int32_t) 0x80000000 : 0x7FFFFFFF; + return aSign ? INT32_MIN : INT32_MAX; } if ( ( aSig0<float_exception_flags |= float_flag_inexact; @@ -6662,9 +6660,9 @@ int64_t float128_to_int64(float128 a, float_status *status) && ( aSig1 || ( aSig0 != LIT64( 0x0001000000000000 ) ) ) ) ) { - return LIT64( 0x7FFFFFFFFFFFFFFF ); + return INT64_MAX; } - return (int64_t) LIT64( 0x8000000000000000 ); + return INT64_MIN; } shortShift128Left( aSig0, aSig1, - shiftCount, &aSig0, &aSig1 ); } @@ -6710,10 +6708,10 @@ int64_t float128_to_int64_round_to_zero(float128 a, float_status *status) else { float_raise(float_flag_invalid, status); if ( ! aSign || ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) ) { - return LIT64( 0x7FFFFFFFFFFFFFFF ); + return INT64_MAX; } } - return (int64_t) LIT64( 0x8000000000000000 ); + return INT64_MIN; } z = ( aSig0<>( ( - shiftCount ) & 63 ) ); if ( (uint64_t) ( aSig1< 0x3FFE)) { float_raise(float_flag_invalid, status); if (float128_is_any_nan(a)) { - return LIT64(0xFFFFFFFFFFFFFFFF); + return UINT64_MAX; } else { return 0; } } if (aExp) { - aSig0 |= LIT64(0x0001000000000000); + aSig0 |= UINT64_C(0x0001000000000000); } shiftCount = 0x402F - aExp; if (shiftCount <= 0) { if (0x403E < aExp) { float_raise(float_flag_invalid, status); - return LIT64(0xFFFFFFFFFFFFFFFF); + return UINT64_MAX; } shortShift128Left(aSig0, aSig1, -shiftCount, &aSig0, &aSig1); } else { -- cgit v1.1 From e932112420f063776f2b9d9e5512830cd6890a7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 13 Aug 2019 12:16:23 +0100 Subject: fpu: replace LIT64 with UINT64_C macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In our quest to eliminate the home rolled LIT64 macro we fixup usage inside the softfloat code. While we are at it we remove some of the extraneous spaces to closer fit the house style. Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson --- fpu/softfloat.c | 118 ++++++++++++++++++++--------------------- include/fpu/softfloat-macros.h | 6 +-- 2 files changed, 62 insertions(+), 62 deletions(-) diff --git a/fpu/softfloat.c b/fpu/softfloat.c index d2cdf4a..7ef0638 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -447,7 +447,7 @@ static inline flag extractFloat32Sign(float32 a) static inline uint64_t extractFloat64Frac(float64 a) { - return float64_val(a) & LIT64(0x000FFFFFFFFFFFFF); + return float64_val(a) & UINT64_C(0x000FFFFFFFFFFFFF); } /*---------------------------------------------------------------------------- @@ -3251,7 +3251,7 @@ float128 float128_default_nan(float_status *status) */ r.low = -(p.frac & 1); r.high = p.frac >> (DECOMPOSED_BINARY_POINT - 48); - r.high |= LIT64(0x7FFF000000000000); + r.high |= UINT64_C(0x7FFF000000000000); r.high |= (uint64_t)p.sign << 63; return r; @@ -3758,7 +3758,7 @@ static float64 roundAndPackFloat64(flag zSign, int zExp, uint64_t zSig, (status->float_detect_tininess == float_tininess_before_rounding) || ( zExp < -1 ) - || ( zSig + roundIncrement < LIT64( 0x8000000000000000 ) ); + || ( zSig + roundIncrement < UINT64_C(0x8000000000000000) ); shift64RightJamming( zSig, - zExp, &zSig ); zExp = 0; roundBits = zSig & 0x3FF; @@ -3858,12 +3858,12 @@ floatx80 roundAndPackFloatx80(int8_t roundingPrecision, flag zSign, roundNearestEven = ( roundingMode == float_round_nearest_even ); if ( roundingPrecision == 80 ) goto precision80; if ( roundingPrecision == 64 ) { - roundIncrement = LIT64( 0x0000000000000400 ); - roundMask = LIT64( 0x00000000000007FF ); + roundIncrement = UINT64_C(0x0000000000000400); + roundMask = UINT64_C(0x00000000000007FF); } else if ( roundingPrecision == 32 ) { - roundIncrement = LIT64( 0x0000008000000000 ); - roundMask = LIT64( 0x000000FFFFFFFFFF ); + roundIncrement = UINT64_C(0x0000008000000000); + roundMask = UINT64_C(0x000000FFFFFFFFFF); } else { goto precision80; @@ -3927,7 +3927,7 @@ floatx80 roundAndPackFloatx80(int8_t roundingPrecision, flag zSign, zSig0 += roundIncrement; if ( zSig0 < roundIncrement ) { ++zExp; - zSig0 = LIT64( 0x8000000000000000 ); + zSig0 = UINT64_C(0x8000000000000000); } roundIncrement = roundMask + 1; if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) { @@ -3957,7 +3957,7 @@ floatx80 roundAndPackFloatx80(int8_t roundingPrecision, flag zSign, if ( 0x7FFD <= (uint32_t) ( zExp - 1 ) ) { if ( ( 0x7FFE < zExp ) || ( ( zExp == 0x7FFE ) - && ( zSig0 == LIT64( 0xFFFFFFFFFFFFFFFF ) ) + && ( zSig0 == UINT64_C(0xFFFFFFFFFFFFFFFF) ) && increment ) ) { @@ -3980,7 +3980,7 @@ floatx80 roundAndPackFloatx80(int8_t roundingPrecision, flag zSign, == float_tininess_before_rounding) || ( zExp < 0 ) || ! increment - || ( zSig0 < LIT64( 0xFFFFFFFFFFFFFFFF ) ); + || ( zSig0 < UINT64_C(0xFFFFFFFFFFFFFFFF) ); shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 ); zExp = 0; if (isTiny && zSig1) { @@ -4022,7 +4022,7 @@ floatx80 roundAndPackFloatx80(int8_t roundingPrecision, flag zSign, ++zSig0; if ( zSig0 == 0 ) { ++zExp; - zSig0 = LIT64( 0x8000000000000000 ); + zSig0 = UINT64_C(0x8000000000000000); } else { zSig0 &= ~ ( ( (uint64_t) ( zSig1<<1 ) == 0 ) & roundNearestEven ); @@ -4084,7 +4084,7 @@ static inline uint64_t extractFloat128Frac1( float128 a ) static inline uint64_t extractFloat128Frac0( float128 a ) { - return a.high & LIT64( 0x0000FFFFFFFFFFFF ); + return a.high & UINT64_C(0x0000FFFFFFFFFFFF); } @@ -4230,8 +4230,8 @@ static float128 roundAndPackFloat128(flag zSign, int32_t zExp, if ( ( 0x7FFD < zExp ) || ( ( zExp == 0x7FFD ) && eq128( - LIT64( 0x0001FFFFFFFFFFFF ), - LIT64( 0xFFFFFFFFFFFFFFFF ), + UINT64_C(0x0001FFFFFFFFFFFF), + UINT64_C(0xFFFFFFFFFFFFFFFF), zSig0, zSig1 ) @@ -4248,8 +4248,8 @@ static float128 roundAndPackFloat128(flag zSign, int32_t zExp, packFloat128( zSign, 0x7FFE, - LIT64( 0x0000FFFFFFFFFFFF ), - LIT64( 0xFFFFFFFFFFFFFFFF ) + UINT64_C(0x0000FFFFFFFFFFFF), + UINT64_C(0xFFFFFFFFFFFFFFFF) ); } return packFloat128( zSign, 0x7FFF, 0, 0 ); @@ -4267,8 +4267,8 @@ static float128 roundAndPackFloat128(flag zSign, int32_t zExp, || lt128( zSig0, zSig1, - LIT64( 0x0001FFFFFFFFFFFF ), - LIT64( 0xFFFFFFFFFFFFFFFF ) + UINT64_C(0x0001FFFFFFFFFFFF), + UINT64_C(0xFFFFFFFFFFFFFFFF) ); shift128ExtraRightJamming( zSig0, zSig1, zSig2, - zExp, &zSig0, &zSig1, &zSig2 ); @@ -5011,7 +5011,7 @@ floatx80 float64_to_floatx80(float64 a, float_status *status) } return packFloatx80( - aSign, aExp + 0x3C00, ( aSig | LIT64( 0x0010000000000000 ) )<<11 ); + aSign, aExp + 0x3C00, (aSig | UINT64_C(0x0010000000000000)) << 11); } @@ -5095,8 +5095,8 @@ float64 float64_rem(float64 a, float64 b, float_status *status) normalizeFloat64Subnormal( aSig, &aExp, &aSig ); } expDiff = aExp - bExp; - aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<11; - bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; + aSig = (aSig | UINT64_C(0x0010000000000000)) << 11; + bSig = (bSig | UINT64_C(0x0010000000000000)) << 11; if ( expDiff < 0 ) { if ( expDiff < -1 ) return a; aSig >>= 1; @@ -5169,13 +5169,13 @@ float64 float64_log2(float64 a, float_status *status) } aExp -= 0x3FF; - aSig |= LIT64( 0x0010000000000000 ); + aSig |= UINT64_C(0x0010000000000000); zSign = aExp < 0; zSig = (uint64_t)aExp << 52; for (i = 1LL << 51; i > 0; i >>= 1) { mul64To128( aSig, aSig, &aSig0, &aSig1 ); aSig = ( aSig0 << 12 ) | ( aSig1 >> 52 ); - if ( aSig & LIT64( 0x0020000000000000 ) ) { + if ( aSig & UINT64_C(0x0020000000000000) ) { aSig >>= 1; zSig |= i; } @@ -5555,7 +5555,7 @@ int64_t floatx80_to_int64_round_to_zero(floatx80 a, float_status *status) aSign = extractFloatx80Sign( a ); shiftCount = aExp - 0x403E; if ( 0 <= shiftCount ) { - aSig &= LIT64( 0x7FFFFFFFFFFFFFFF ); + aSig &= UINT64_C(0x7FFFFFFFFFFFFFFF); if ( ( a.high != 0xC03E ) || aSig ) { float_raise(float_flag_invalid, status); if ( ! aSign || ( ( aExp == 0x7FFF ) && aSig ) ) { @@ -5724,23 +5724,23 @@ floatx80 floatx80_round_to_int(floatx80 a, float_status *status) if ( ( aExp == 0x3FFE ) && (uint64_t) ( extractFloatx80Frac( a )<<1 ) ) { return - packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) ); + packFloatx80( aSign, 0x3FFF, UINT64_C(0x8000000000000000)); } break; case float_round_ties_away: if (aExp == 0x3FFE) { - return packFloatx80(aSign, 0x3FFF, LIT64(0x8000000000000000)); + return packFloatx80(aSign, 0x3FFF, UINT64_C(0x8000000000000000)); } break; case float_round_down: return aSign ? - packFloatx80( 1, 0x3FFF, LIT64( 0x8000000000000000 ) ) + packFloatx80( 1, 0x3FFF, UINT64_C(0x8000000000000000)) : packFloatx80( 0, 0, 0 ); case float_round_up: return aSign ? packFloatx80( 1, 0, 0 ) - : packFloatx80( 0, 0x3FFF, LIT64( 0x8000000000000000 ) ); + : packFloatx80( 0, 0x3FFF, UINT64_C(0x8000000000000000)); } return packFloatx80( aSign, 0, 0 ); } @@ -5776,7 +5776,7 @@ floatx80 floatx80_round_to_int(floatx80 a, float_status *status) z.low &= ~ roundBitsMask; if ( z.low == 0 ) { ++z.high; - z.low = LIT64( 0x8000000000000000 ); + z.low = UINT64_C(0x8000000000000000); } if (z.low != a.low) { status->float_exception_flags |= float_flag_inexact; @@ -5849,7 +5849,7 @@ static floatx80 addFloatx80Sigs(floatx80 a, floatx80 b, flag zSign, if ( (int64_t) zSig0 < 0 ) goto roundAndPack; shiftRight1: shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 ); - zSig0 |= LIT64( 0x8000000000000000 ); + zSig0 |= UINT64_C(0x8000000000000000); ++zExp; roundAndPack: return roundAndPackFloatx80(status->floatx80_rounding_precision, @@ -6171,7 +6171,7 @@ floatx80 floatx80_rem(floatx80 a, floatx80 b, float_status *status) if ( (uint64_t) ( aSig0<<1 ) == 0 ) return a; normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); } - bSig |= LIT64( 0x8000000000000000 ); + bSig |= UINT64_C(0x8000000000000000); zSign = aSign; expDiff = aExp - bExp; aSig1 = 0; @@ -6273,7 +6273,7 @@ floatx80 floatx80_sqrt(floatx80 a, float_status *status) add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); } zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); - if ( ( zSig1 & LIT64( 0x3FFFFFFFFFFFFFFF ) ) <= 5 ) { + if ( ( zSig1 & UINT64_C(0x3FFFFFFFFFFFFFFF) ) <= 5 ) { if ( zSig1 == 0 ) zSig1 = 1; mul64To128( doubleZSig0, zSig1, &term1, &term2 ); sub128( rem1, 0, term1, term2, &rem1, &rem2 ); @@ -6572,7 +6572,7 @@ int32_t float128_to_int32(float128 a, float_status *status) aExp = extractFloat128Exp( a ); aSign = extractFloat128Sign( a ); if ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) aSign = 0; - if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); + if ( aExp ) aSig0 |= UINT64_C(0x0001000000000000); aSig0 |= ( aSig1 != 0 ); shiftCount = 0x4028 - aExp; if ( 0 < shiftCount ) shift64RightJamming( aSig0, shiftCount, &aSig0 ); @@ -6612,7 +6612,7 @@ int32_t float128_to_int32_round_to_zero(float128 a, float_status *status) } return 0; } - aSig0 |= LIT64( 0x0001000000000000 ); + aSig0 |= UINT64_C(0x0001000000000000); shiftCount = 0x402F - aExp; savedASig = aSig0; aSig0 >>= shiftCount; @@ -6650,14 +6650,14 @@ int64_t float128_to_int64(float128 a, float_status *status) aSig0 = extractFloat128Frac0( a ); aExp = extractFloat128Exp( a ); aSign = extractFloat128Sign( a ); - if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); + if ( aExp ) aSig0 |= UINT64_C(0x0001000000000000); shiftCount = 0x402F - aExp; if ( shiftCount <= 0 ) { if ( 0x403E < aExp ) { float_raise(float_flag_invalid, status); if ( ! aSign || ( ( aExp == 0x7FFF ) - && ( aSig1 || ( aSig0 != LIT64( 0x0001000000000000 ) ) ) + && ( aSig1 || ( aSig0 != UINT64_C(0x0001000000000000) ) ) ) ) { return INT64_MAX; @@ -6694,13 +6694,13 @@ int64_t float128_to_int64_round_to_zero(float128 a, float_status *status) aSig0 = extractFloat128Frac0( a ); aExp = extractFloat128Exp( a ); aSign = extractFloat128Sign( a ); - if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); + if ( aExp ) aSig0 |= UINT64_C(0x0001000000000000); shiftCount = aExp - 0x402F; if ( 0 < shiftCount ) { if ( 0x403E <= aExp ) { - aSig0 &= LIT64( 0x0000FFFFFFFFFFFF ); - if ( ( a.high == LIT64( 0xC03E000000000000 ) ) - && ( aSig1 < LIT64( 0x0002000000000000 ) ) ) { + aSig0 &= UINT64_C(0x0000FFFFFFFFFFFF); + if ( ( a.high == UINT64_C(0xC03E000000000000) ) + && ( aSig1 < UINT64_C(0x0002000000000000) ) ) { if (aSig1) { status->float_exception_flags |= float_flag_inexact; } @@ -6913,7 +6913,7 @@ float64 float128_to_float64(float128 a, float_status *status) shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); aSig0 |= ( aSig1 != 0 ); if ( aExp || aSig0 ) { - aSig0 |= LIT64( 0x4000000000000000 ); + aSig0 |= UINT64_C(0x4000000000000000); aExp -= 0x3C01; } return roundAndPackFloat64(aSign, aExp, aSig0, status); @@ -6949,7 +6949,7 @@ floatx80 float128_to_floatx80(float128 a, float_status *status) normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); } else { - aSig0 |= LIT64( 0x0001000000000000 ); + aSig0 |= UINT64_C(0x0001000000000000); } shortShift128Left( aSig0, aSig1, 15, &aSig0, &aSig1 ); return roundAndPackFloatx80(80, aSign, aExp, aSig0, aSig1, status); @@ -7145,7 +7145,7 @@ static float128 addFloat128Sigs(float128 a, float128 b, flag zSign, --expDiff; } else { - bSig0 |= LIT64( 0x0001000000000000 ); + bSig0 |= UINT64_C(0x0001000000000000); } shift128ExtraRightJamming( bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 ); @@ -7162,7 +7162,7 @@ static float128 addFloat128Sigs(float128 a, float128 b, flag zSign, ++expDiff; } else { - aSig0 |= LIT64( 0x0001000000000000 ); + aSig0 |= UINT64_C(0x0001000000000000); } shift128ExtraRightJamming( aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 ); @@ -7186,14 +7186,14 @@ static float128 addFloat128Sigs(float128 a, float128 b, flag zSign, return packFloat128( zSign, 0, zSig0, zSig1 ); } zSig2 = 0; - zSig0 |= LIT64( 0x0002000000000000 ); + zSig0 |= UINT64_C(0x0002000000000000); zExp = aExp; goto shiftRight1; } - aSig0 |= LIT64( 0x0001000000000000 ); + aSig0 |= UINT64_C(0x0001000000000000); add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); --zExp; - if ( zSig0 < LIT64( 0x0002000000000000 ) ) goto roundAndPack; + if ( zSig0 < UINT64_C(0x0002000000000000) ) goto roundAndPack; ++zExp; shiftRight1: shift128ExtraRightJamming( @@ -7257,10 +7257,10 @@ static float128 subFloat128Sigs(float128 a, float128 b, flag zSign, ++expDiff; } else { - aSig0 |= LIT64( 0x4000000000000000 ); + aSig0 |= UINT64_C(0x4000000000000000); } shift128RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); - bSig0 |= LIT64( 0x4000000000000000 ); + bSig0 |= UINT64_C(0x4000000000000000); bBigger: sub128( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 ); zExp = bExp; @@ -7277,10 +7277,10 @@ static float128 subFloat128Sigs(float128 a, float128 b, flag zSign, --expDiff; } else { - bSig0 |= LIT64( 0x4000000000000000 ); + bSig0 |= UINT64_C(0x4000000000000000); } shift128RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 ); - aSig0 |= LIT64( 0x4000000000000000 ); + aSig0 |= UINT64_C(0x4000000000000000); aBigger: sub128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); zExp = aExp; @@ -7382,12 +7382,12 @@ float128 float128_mul(float128 a, float128 b, float_status *status) normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); } zExp = aExp + bExp - 0x4000; - aSig0 |= LIT64( 0x0001000000000000 ); + aSig0 |= UINT64_C(0x0001000000000000); shortShift128Left( bSig0, bSig1, 16, &bSig0, &bSig1 ); mul128To256( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 ); add128( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 ); zSig2 |= ( zSig3 != 0 ); - if ( LIT64( 0x0002000000000000 ) <= zSig0 ) { + if (UINT64_C( 0x0002000000000000) <= zSig0 ) { shift128ExtraRightJamming( zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); ++zExp; @@ -7454,9 +7454,9 @@ float128 float128_div(float128 a, float128 b, float_status *status) } zExp = aExp - bExp + 0x3FFD; shortShift128Left( - aSig0 | LIT64( 0x0001000000000000 ), aSig1, 15, &aSig0, &aSig1 ); + aSig0 | UINT64_C(0x0001000000000000), aSig1, 15, &aSig0, &aSig1 ); shortShift128Left( - bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); + bSig0 | UINT64_C(0x0001000000000000), bSig1, 15, &bSig0, &bSig1 ); if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) { shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 ); ++zExp; @@ -7532,14 +7532,14 @@ float128 float128_rem(float128 a, float128 b, float_status *status) expDiff = aExp - bExp; if ( expDiff < -1 ) return a; shortShift128Left( - aSig0 | LIT64( 0x0001000000000000 ), + aSig0 | UINT64_C(0x0001000000000000), aSig1, 15 - ( expDiff < 0 ), &aSig0, &aSig1 ); shortShift128Left( - bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); + bSig0 | UINT64_C(0x0001000000000000), bSig1, 15, &bSig0, &bSig1 ); q = le128( bSig0, bSig1, aSig0, aSig1 ); if ( q ) sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); expDiff -= 64; @@ -7625,7 +7625,7 @@ float128 float128_sqrt(float128 a, float_status *status) normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); } zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFE; - aSig0 |= LIT64( 0x0001000000000000 ); + aSig0 |= UINT64_C(0x0001000000000000); zSig0 = estimateSqrt32( aExp, aSig0>>17 ); shortShift128Left( aSig0, aSig1, 13 - ( aExp & 1 ), &aSig0, &aSig1 ); zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); @@ -8046,7 +8046,7 @@ float128 float128_scalbn(float128 a, int n, float_status *status) return a; } if (aExp != 0) { - aSig0 |= LIT64( 0x0001000000000000 ); + aSig0 |= UINT64_C(0x0001000000000000); } else if (aSig0 == 0 && aSig1 == 0) { return a; } else { diff --git a/include/fpu/softfloat-macros.h b/include/fpu/softfloat-macros.h index be83a83..3a95673 100644 --- a/include/fpu/softfloat-macros.h +++ b/include/fpu/softfloat-macros.h @@ -618,13 +618,13 @@ static inline uint64_t estimateDiv128To64(uint64_t a0, uint64_t a1, uint64_t b) uint64_t rem0, rem1, term0, term1; uint64_t z; - if ( b <= a0 ) return LIT64( 0xFFFFFFFFFFFFFFFF ); + if ( b <= a0 ) return UINT64_C(0xFFFFFFFFFFFFFFFF); b0 = b>>32; - z = ( b0<<32 <= a0 ) ? LIT64( 0xFFFFFFFF00000000 ) : ( a0 / b0 )<<32; + z = ( b0<<32 <= a0 ) ? UINT64_C(0xFFFFFFFF00000000) : ( a0 / b0 )<<32; mul64To128( b, z, &term0, &term1 ); sub128( a0, a1, term0, term1, &rem0, &rem1 ); while ( ( (int64_t) rem0 ) < 0 ) { - z -= LIT64( 0x100000000 ); + z -= UINT64_C(0x100000000); b1 = b<<32; add128( rem0, rem1, b0, b1, &rem0, &rem1 ); } -- cgit v1.1 From e23263004d5fea809ad0f78c523f498e04ba788f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 13 Aug 2019 12:19:22 +0100 Subject: target/m68k: replace LIT64 with UINT64_C macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In our quest to eliminate the home rolled LIT64 macro we fixup usage inside for m68k's many constants. Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson --- target/m68k/softfloat.c | 98 ++++++++++++++++++++++++------------------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c index 591a6f1..24c313e 100644 --- a/target/m68k/softfloat.c +++ b/target/m68k/softfloat.c @@ -26,7 +26,7 @@ #define pi_exp 0x4000 #define piby2_exp 0x3FFF -#define pi_sig LIT64(0xc90fdaa22168c235) +#define pi_sig UINT64_C(0xc90fdaa22168c235) static floatx80 propagateFloatx80NaNOneArg(floatx80 a, float_status *status) { @@ -87,7 +87,7 @@ floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status) } normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); } - bSig |= LIT64(0x8000000000000000); + bSig |= UINT64_C(0x8000000000000000); zSign = aSign; expDiff = aExp - bExp; aSig1 = 0; @@ -289,7 +289,7 @@ floatx80 floatx80_move(floatx80 a, float_status *status) */ #define one_exp 0x3FFF -#define one_sig LIT64(0x8000000000000000) +#define one_sig UINT64_C(0x8000000000000000) /* * Function for compactifying extended double-precision floating point values. @@ -373,7 +373,7 @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status) k = aExp - 0x3FFF; fp1 = int32_to_floatx80(k, status); - fSig = (aSig & LIT64(0xFE00000000000000)) | LIT64(0x0100000000000000); + fSig = (aSig & UINT64_C(0xFE00000000000000)) | UINT64_C(0x0100000000000000); j = (fSig >> 56) & 0x7E; /* DISPLACEMENT FOR 1/F */ f = packFloatx80(0, 0x3FFF, fSig); /* F */ @@ -384,7 +384,7 @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status) lp1cont1: /* LP1CONT1 */ fp0 = floatx80_mul(fp0, log_tbl[j], status); /* FP0 IS U = (Y-F)/F */ - logof2 = packFloatx80(0, 0x3FFE, LIT64(0xB17217F7D1CF79AC)); + logof2 = packFloatx80(0, 0x3FFE, UINT64_C(0xB17217F7D1CF79AC)); klog2 = floatx80_mul(fp1, logof2, status); /* FP1 IS K*LOG2 */ fp2 = floatx80_mul(fp0, fp0, status); /* FP2 IS V=U*U */ @@ -431,7 +431,7 @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status) } else if (compact < 0x3FFEF07D || compact > 0x3FFF8841) { /* |X| < 1/16 or |X| > -1/16 */ /* LP1CARE */ - fSig = (aSig & LIT64(0xFE00000000000000)) | LIT64(0x0100000000000000); + fSig = (aSig & UINT64_C(0xFE00000000000000)) | UINT64_C(0x0100000000000000); f = packFloatx80(0, 0x3FFF, fSig); /* F */ j = (fSig >> 56) & 0x7E; /* DISPLACEMENT FOR 1/F */ @@ -562,7 +562,7 @@ floatx80 floatx80_logn(floatx80 a, float_status *status) k += adjk; fp1 = int32_to_floatx80(k, status); - fSig = (aSig & LIT64(0xFE00000000000000)) | LIT64(0x0100000000000000); + fSig = (aSig & UINT64_C(0xFE00000000000000)) | UINT64_C(0x0100000000000000); j = (fSig >> 56) & 0x7E; /* DISPLACEMENT FOR 1/F */ f = packFloatx80(0, 0x3FFF, fSig); /* F */ @@ -572,7 +572,7 @@ floatx80 floatx80_logn(floatx80 a, float_status *status) /* LP1CONT1 */ fp0 = floatx80_mul(fp0, log_tbl[j], status); /* FP0 IS U = (Y-F)/F */ - logof2 = packFloatx80(0, 0x3FFE, LIT64(0xB17217F7D1CF79AC)); + logof2 = packFloatx80(0, 0x3FFE, UINT64_C(0xB17217F7D1CF79AC)); klog2 = floatx80_mul(fp1, logof2, status); /* FP1 IS K*LOG2 */ fp2 = floatx80_mul(fp0, fp0, status); /* FP2 IS V=U*U */ @@ -712,7 +712,7 @@ floatx80 floatx80_log10(floatx80 a, float_status *status) status->floatx80_rounding_precision = 80; fp0 = floatx80_logn(a, status); - fp1 = packFloatx80(0, 0x3FFD, LIT64(0xDE5BD8A937287195)); /* INV_L10 */ + fp1 = packFloatx80(0, 0x3FFD, UINT64_C(0xDE5BD8A937287195)); /* INV_L10 */ status->float_rounding_mode = user_rnd_mode; status->floatx80_rounding_precision = user_rnd_prec; @@ -778,7 +778,7 @@ floatx80 floatx80_log2(floatx80 a, float_status *status) a = int32_to_floatx80(aExp - 0x3FFF, status); } else { fp0 = floatx80_logn(a, status); - fp1 = packFloatx80(0, 0x3FFF, LIT64(0xB8AA3B295C17F0BC)); /* INV_L2 */ + fp1 = packFloatx80(0, 0x3FFF, UINT64_C(0xB8AA3B295C17F0BC)); /* INV_L2 */ status->float_rounding_mode = user_rnd_mode; status->floatx80_rounding_precision = user_rnd_prec; @@ -862,7 +862,7 @@ floatx80 floatx80_etox(floatx80 a, float_status *status) fp0 = floatx80_mul(fp0, float32_to_floatx80( make_float32(0xBC317218), status), status); /* N * L1, L1 = lead(-log2/64) */ - l2 = packFloatx80(0, 0x3FDC, LIT64(0x82E308654361C4C6)); + l2 = packFloatx80(0, 0x3FDC, UINT64_C(0x82E308654361C4C6)); fp2 = floatx80_mul(fp2, l2, status); /* N * L2, L1+L2 = -log2/64 */ fp0 = floatx80_add(fp0, fp1, status); /* X + N*L1 */ fp0 = floatx80_add(fp0, fp2, status); /* R */ @@ -1082,7 +1082,7 @@ floatx80 floatx80_twotox(floatx80 a, float_status *status) make_float32(0x3C800000), status), status); /* (1/64)*N */ fp0 = floatx80_sub(fp0, fp1, status); /* X - (1/64)*INT(64 X) */ - fp2 = packFloatx80(0, 0x3FFE, LIT64(0xB17217F7D1CF79AC)); /* LOG2 */ + fp2 = packFloatx80(0, 0x3FFE, UINT64_C(0xB17217F7D1CF79AC)); /* LOG2 */ fp0 = floatx80_mul(fp0, fp2, status); /* R */ /* EXPR */ @@ -1233,11 +1233,11 @@ floatx80 floatx80_tentox(floatx80 a, float_status *status) fp1 = floatx80_mul(fp1, float64_to_floatx80( make_float64(0x3F734413509F8000), status), status); /* N*(LOG2/64LOG10)_LEAD */ - fp3 = packFloatx80(1, 0x3FCD, LIT64(0xC0219DC1DA994FD2)); + fp3 = packFloatx80(1, 0x3FCD, UINT64_C(0xC0219DC1DA994FD2)); fp2 = floatx80_mul(fp2, fp3, status); /* N*(LOG2/64LOG10)_TRAIL */ fp0 = floatx80_sub(fp0, fp1, status); /* X - N L_LEAD */ fp0 = floatx80_sub(fp0, fp2, status); /* X - N L_TRAIL */ - fp2 = packFloatx80(0, 0x4000, LIT64(0x935D8DDDAAA8AC17)); /* LOG10 */ + fp2 = packFloatx80(0, 0x4000, UINT64_C(0x935D8DDDAAA8AC17)); /* LOG10 */ fp0 = floatx80_mul(fp0, fp2, status); /* R */ /* EXPR */ @@ -1329,9 +1329,9 @@ floatx80 floatx80_tan(floatx80 a, float_status *status) fp1 = packFloatx80(0, 0, 0); if (compact == 0x7FFEFFFF) { twopi1 = packFloatx80(aSign ^ 1, 0x7FFE, - LIT64(0xC90FDAA200000000)); + UINT64_C(0xC90FDAA200000000)); twopi2 = packFloatx80(aSign ^ 1, 0x7FDC, - LIT64(0x85A308D300000000)); + UINT64_C(0x85A308D300000000)); fp0 = floatx80_add(fp0, twopi1, status); fp1 = fp0; fp0 = floatx80_add(fp0, twopi2, status); @@ -1350,9 +1350,9 @@ floatx80 floatx80_tan(floatx80 a, float_status *status) endflag = 0; } invtwopi = packFloatx80(0, 0x3FFE - l, - LIT64(0xA2F9836E4E44152A)); /* INVTWOPI */ - twopi1 = packFloatx80(0, 0x3FFF + l, LIT64(0xC90FDAA200000000)); - twopi2 = packFloatx80(0, 0x3FDD + l, LIT64(0x85A308D300000000)); + UINT64_C(0xA2F9836E4E44152A)); /* INVTWOPI */ + twopi1 = packFloatx80(0, 0x3FFF + l, UINT64_C(0xC90FDAA200000000)); + twopi2 = packFloatx80(0, 0x3FDD + l, UINT64_C(0x85A308D300000000)); /* SIGN(INARG)*2^63 IN SGL */ twoto63 = packFloat32(xSign, 0xBE, 0); @@ -1415,17 +1415,17 @@ floatx80 floatx80_tan(floatx80 a, float_status *status) fp3 = floatx80_add(fp3, float64_to_floatx80( make_float64(0xBF346F59B39BA65F), status), status); /* Q3+SQ4 */ - fp4 = packFloatx80(0, 0x3FF6, LIT64(0xE073D3FC199C4A00)); + fp4 = packFloatx80(0, 0x3FF6, UINT64_C(0xE073D3FC199C4A00)); fp2 = floatx80_add(fp2, fp4, status); /* P2+SP3 */ fp3 = floatx80_mul(fp3, fp0, status); /* S(Q3+SQ4) */ fp2 = floatx80_mul(fp2, fp0, status); /* S(P2+SP3) */ - fp4 = packFloatx80(0, 0x3FF9, LIT64(0xD23CD68415D95FA1)); + fp4 = packFloatx80(0, 0x3FF9, UINT64_C(0xD23CD68415D95FA1)); fp3 = floatx80_add(fp3, fp4, status); /* Q2+S(Q3+SQ4) */ - fp4 = packFloatx80(1, 0x3FFC, LIT64(0x8895A6C5FB423BCA)); + fp4 = packFloatx80(1, 0x3FFC, UINT64_C(0x8895A6C5FB423BCA)); fp2 = floatx80_add(fp2, fp4, status); /* P1+S(P2+SP3) */ fp3 = floatx80_mul(fp3, fp0, status); /* S(Q2+S(Q3+SQ4)) */ fp2 = floatx80_mul(fp2, fp0, status); /* S(P1+S(P2+SP3)) */ - fp4 = packFloatx80(1, 0x3FFD, LIT64(0xEEF57E0DA84BC8CE)); + fp4 = packFloatx80(1, 0x3FFD, UINT64_C(0xEEF57E0DA84BC8CE)); fp3 = floatx80_add(fp3, fp4, status); /* Q1+S(Q2+S(Q3+SQ4)) */ fp2 = floatx80_mul(fp2, fp1, status); /* RS(P1+S(P2+SP3)) */ fp0 = floatx80_mul(fp0, fp3, status); /* S(Q1+S(Q2+S(Q3+SQ4))) */ @@ -1459,17 +1459,17 @@ floatx80 floatx80_tan(floatx80 a, float_status *status) fp3 = floatx80_add(fp3, float64_to_floatx80( make_float64(0xBF346F59B39BA65F), status), status); /* Q3+SQ4 */ - fp4 = packFloatx80(0, 0x3FF6, LIT64(0xE073D3FC199C4A00)); + fp4 = packFloatx80(0, 0x3FF6, UINT64_C(0xE073D3FC199C4A00)); fp2 = floatx80_add(fp2, fp4, status); /* P2+SP3 */ fp3 = floatx80_mul(fp3, fp1, status); /* S(Q3+SQ4) */ fp2 = floatx80_mul(fp2, fp1, status); /* S(P2+SP3) */ - fp4 = packFloatx80(0, 0x3FF9, LIT64(0xD23CD68415D95FA1)); + fp4 = packFloatx80(0, 0x3FF9, UINT64_C(0xD23CD68415D95FA1)); fp3 = floatx80_add(fp3, fp4, status); /* Q2+S(Q3+SQ4) */ - fp4 = packFloatx80(1, 0x3FFC, LIT64(0x8895A6C5FB423BCA)); + fp4 = packFloatx80(1, 0x3FFC, UINT64_C(0x8895A6C5FB423BCA)); fp2 = floatx80_add(fp2, fp4, status); /* P1+S(P2+SP3) */ fp3 = floatx80_mul(fp3, fp1, status); /* S(Q2+S(Q3+SQ4)) */ fp2 = floatx80_mul(fp2, fp1, status); /* S(P1+S(P2+SP3)) */ - fp4 = packFloatx80(1, 0x3FFD, LIT64(0xEEF57E0DA84BC8CE)); + fp4 = packFloatx80(1, 0x3FFD, UINT64_C(0xEEF57E0DA84BC8CE)); fp3 = floatx80_add(fp3, fp4, status); /* Q1+S(Q2+S(Q3+SQ4)) */ fp2 = floatx80_mul(fp2, fp0, status); /* RS(P1+S(P2+SP3)) */ fp1 = floatx80_mul(fp1, fp3, status); /* S(Q1+S(Q2+S(Q3+SQ4))) */ @@ -1539,9 +1539,9 @@ floatx80 floatx80_sin(floatx80 a, float_status *status) fp1 = packFloatx80(0, 0, 0); if (compact == 0x7FFEFFFF) { twopi1 = packFloatx80(aSign ^ 1, 0x7FFE, - LIT64(0xC90FDAA200000000)); + UINT64_C(0xC90FDAA200000000)); twopi2 = packFloatx80(aSign ^ 1, 0x7FDC, - LIT64(0x85A308D300000000)); + UINT64_C(0x85A308D300000000)); fp0 = floatx80_add(fp0, twopi1, status); fp1 = fp0; fp0 = floatx80_add(fp0, twopi2, status); @@ -1560,9 +1560,9 @@ floatx80 floatx80_sin(floatx80 a, float_status *status) endflag = 0; } invtwopi = packFloatx80(0, 0x3FFE - l, - LIT64(0xA2F9836E4E44152A)); /* INVTWOPI */ - twopi1 = packFloatx80(0, 0x3FFF + l, LIT64(0xC90FDAA200000000)); - twopi2 = packFloatx80(0, 0x3FDD + l, LIT64(0x85A308D300000000)); + UINT64_C(0xA2F9836E4E44152A)); /* INVTWOPI */ + twopi1 = packFloatx80(0, 0x3FFF + l, UINT64_C(0xC90FDAA200000000)); + twopi2 = packFloatx80(0, 0x3FDD + l, UINT64_C(0x85A308D300000000)); /* SIGN(INARG)*2^63 IN SGL */ twoto63 = packFloat32(xSign, 0xBE, 0); @@ -1650,11 +1650,11 @@ floatx80 floatx80_sin(floatx80 a, float_status *status) fp2 = floatx80_add(fp2, float64_to_floatx80( make_float64(0x3EFA01A01A01D423), status), status); /* B4+T(B6+TB8) */ - fp4 = packFloatx80(1, 0x3FF5, LIT64(0xB60B60B60B61D438)); + fp4 = packFloatx80(1, 0x3FF5, UINT64_C(0xB60B60B60B61D438)); fp3 = floatx80_add(fp3, fp4, status); /* B3+T(B5+TB7) */ fp2 = floatx80_mul(fp2, fp1, status); /* T(B4+T(B6+TB8)) */ fp1 = floatx80_mul(fp1, fp3, status); /* T(B3+T(B5+TB7)) */ - fp4 = packFloatx80(0, 0x3FFA, LIT64(0xAAAAAAAAAAAAAB5E)); + fp4 = packFloatx80(0, 0x3FFA, UINT64_C(0xAAAAAAAAAAAAAB5E)); fp2 = floatx80_add(fp2, fp4, status); /* B2+T(B4+T(B6+TB8)) */ fp1 = floatx80_add(fp1, float32_to_floatx80( make_float32(0xBF000000), status), @@ -1702,11 +1702,11 @@ floatx80 floatx80_sin(floatx80 a, float_status *status) fp3 = floatx80_add(fp3, float64_to_floatx80( make_float64(0xBF2A01A01A018B59), status), status); /* A3+T(A5+TA7) */ - fp4 = packFloatx80(0, 0x3FF8, LIT64(0x88888888888859AF)); + fp4 = packFloatx80(0, 0x3FF8, UINT64_C(0x88888888888859AF)); fp2 = floatx80_add(fp2, fp4, status); /* A2+T(A4+TA6) */ fp1 = floatx80_mul(fp1, fp3, status); /* T(A3+T(A5+TA7)) */ fp2 = floatx80_mul(fp2, fp0, status); /* S(A2+T(A4+TA6)) */ - fp4 = packFloatx80(1, 0x3FFC, LIT64(0xAAAAAAAAAAAAAA99)); + fp4 = packFloatx80(1, 0x3FFC, UINT64_C(0xAAAAAAAAAAAAAA99)); fp1 = floatx80_add(fp1, fp4, status); /* A1+T(A3+T(A5+TA7)) */ fp1 = floatx80_add(fp1, fp2, status); /* [A1+T(A3+T(A5+TA7))]+ @@ -1778,9 +1778,9 @@ floatx80 floatx80_cos(floatx80 a, float_status *status) fp1 = packFloatx80(0, 0, 0); if (compact == 0x7FFEFFFF) { twopi1 = packFloatx80(aSign ^ 1, 0x7FFE, - LIT64(0xC90FDAA200000000)); + UINT64_C(0xC90FDAA200000000)); twopi2 = packFloatx80(aSign ^ 1, 0x7FDC, - LIT64(0x85A308D300000000)); + UINT64_C(0x85A308D300000000)); fp0 = floatx80_add(fp0, twopi1, status); fp1 = fp0; fp0 = floatx80_add(fp0, twopi2, status); @@ -1799,9 +1799,9 @@ floatx80 floatx80_cos(floatx80 a, float_status *status) endflag = 0; } invtwopi = packFloatx80(0, 0x3FFE - l, - LIT64(0xA2F9836E4E44152A)); /* INVTWOPI */ - twopi1 = packFloatx80(0, 0x3FFF + l, LIT64(0xC90FDAA200000000)); - twopi2 = packFloatx80(0, 0x3FDD + l, LIT64(0x85A308D300000000)); + UINT64_C(0xA2F9836E4E44152A)); /* INVTWOPI */ + twopi1 = packFloatx80(0, 0x3FFF + l, UINT64_C(0xC90FDAA200000000)); + twopi2 = packFloatx80(0, 0x3FDD + l, UINT64_C(0x85A308D300000000)); /* SIGN(INARG)*2^63 IN SGL */ twoto63 = packFloat32(xSign, 0xBE, 0); @@ -1890,11 +1890,11 @@ floatx80 floatx80_cos(floatx80 a, float_status *status) fp2 = floatx80_add(fp2, float64_to_floatx80( make_float64(0x3EFA01A01A01D423), status), status); /* B4+T(B6+TB8) */ - fp4 = packFloatx80(1, 0x3FF5, LIT64(0xB60B60B60B61D438)); + fp4 = packFloatx80(1, 0x3FF5, UINT64_C(0xB60B60B60B61D438)); fp3 = floatx80_add(fp3, fp4, status); /* B3+T(B5+TB7) */ fp2 = floatx80_mul(fp2, fp1, status); /* T(B4+T(B6+TB8)) */ fp1 = floatx80_mul(fp1, fp3, status); /* T(B3+T(B5+TB7)) */ - fp4 = packFloatx80(0, 0x3FFA, LIT64(0xAAAAAAAAAAAAAB5E)); + fp4 = packFloatx80(0, 0x3FFA, UINT64_C(0xAAAAAAAAAAAAAB5E)); fp2 = floatx80_add(fp2, fp4, status); /* B2+T(B4+T(B6+TB8)) */ fp1 = floatx80_add(fp1, float32_to_floatx80( make_float32(0xBF000000), status), @@ -1941,11 +1941,11 @@ floatx80 floatx80_cos(floatx80 a, float_status *status) fp3 = floatx80_add(fp3, float64_to_floatx80( make_float64(0xBF2A01A01A018B59), status), status); /* A3+T(A5+TA7) */ - fp4 = packFloatx80(0, 0x3FF8, LIT64(0x88888888888859AF)); + fp4 = packFloatx80(0, 0x3FF8, UINT64_C(0x88888888888859AF)); fp2 = floatx80_add(fp2, fp4, status); /* A2+T(A4+TA6) */ fp1 = floatx80_mul(fp1, fp3, status); /* T(A3+T(A5+TA7)) */ fp2 = floatx80_mul(fp2, fp0, status); /* S(A2+T(A4+TA6)) */ - fp4 = packFloatx80(1, 0x3FFC, LIT64(0xAAAAAAAAAAAAAA99)); + fp4 = packFloatx80(1, 0x3FFC, UINT64_C(0xAAAAAAAAAAAAAA99)); fp1 = floatx80_add(fp1, fp4, status); /* A1+T(A3+T(A5+TA7)) */ fp1 = floatx80_add(fp1, fp2, status); /* [A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))] */ @@ -2114,8 +2114,8 @@ floatx80 floatx80_atan(floatx80 a, float_status *status) } } } else { - aSig &= LIT64(0xF800000000000000); - aSig |= LIT64(0x0400000000000000); + aSig &= UINT64_C(0xF800000000000000); + aSig |= UINT64_C(0x0400000000000000); xsave = packFloatx80(aSign, aExp, aSig); /* F */ fp0 = a; fp1 = a; /* X */ @@ -2430,7 +2430,7 @@ floatx80 floatx80_etoxm1(floatx80 a, float_status *status) fp0 = floatx80_mul(fp0, float32_to_floatx80( make_float32(0xBC317218), status), status); /* N * L1, L1 = lead(-log2/64) */ - l2 = packFloatx80(0, 0x3FDC, LIT64(0x82E308654361C4C6)); + l2 = packFloatx80(0, 0x3FDC, UINT64_C(0x82E308654361C4C6)); fp2 = floatx80_mul(fp2, l2, status); /* N * L2, L1+L2 = -log2/64 */ fp0 = floatx80_add(fp0, fp1, status); /* X + N*L1 */ fp0 = floatx80_add(fp0, fp2, status); /* R */ @@ -2562,7 +2562,7 @@ floatx80 floatx80_etoxm1(floatx80 a, float_status *status) fp2 = floatx80_add(fp2, float64_to_floatx80( make_float64(0x3FA5555555555555), status), status); /* B3 */ - fp3 = packFloatx80(0, 0x3FFC, LIT64(0xAAAAAAAAAAAAAAAB)); + fp3 = packFloatx80(0, 0x3FFC, UINT64_C(0xAAAAAAAAAAAAAAAB)); fp1 = floatx80_add(fp1, fp3, status); /* B2 */ fp2 = floatx80_mul(fp2, fp0, status); fp1 = floatx80_mul(fp1, fp0, status); -- cgit v1.1 From 472038ccf5d69ebcad44d835488a36ee640c219f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 13 Aug 2019 12:29:32 +0100 Subject: fpu: remove the LIT64 macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now the rest of the code has been cleaned up we can remove this. Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson --- include/fpu/softfloat.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 3ff3fa5..d9333eb 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -82,8 +82,6 @@ this code that are retained. #ifndef SOFTFLOAT_H #define SOFTFLOAT_H -#define LIT64( a ) a##LL - /*---------------------------------------------------------------------------- | Software IEC/IEEE floating-point ordering relations *----------------------------------------------------------------------------*/ -- cgit v1.1 From e34c47ea3fb5f324b58db117b3c010a494c8d6ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 8 Aug 2019 15:11:08 +0100 Subject: fpu: move inline helpers into a separate header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are a bunch of users of the inline helpers who do not need access to the entire softfloat API. Move those inline helpers into a new header file which can be included without bringing in the rest of the world. Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé --- include/fpu/softfloat-helpers.h | 132 ++++++++++++++++++++++++++++++++++++++++ include/fpu/softfloat.h | 63 +------------------ 2 files changed, 133 insertions(+), 62 deletions(-) create mode 100644 include/fpu/softfloat-helpers.h diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h new file mode 100644 index 0000000..e0baf24c --- /dev/null +++ b/include/fpu/softfloat-helpers.h @@ -0,0 +1,132 @@ +/* + * QEMU float support - standalone helpers + * + * This is provided for files that don't need the access to the full + * set of softfloat functions. Typically this is cpu initialisation + * code which wants to set default rounding and exceptions modes. + * + * The code in this source file is derived from release 2a of the SoftFloat + * IEC/IEEE Floating-point Arithmetic Package. Those parts of the code (and + * some later contributions) are provided under that license, as detailed below. + * It has subsequently been modified by contributors to the QEMU Project, + * so some portions are provided under: + * the SoftFloat-2a license + * the BSD license + * GPL-v2-or-later + * + * Any future contributions to this file after December 1st 2014 will be + * taken to be licensed under the Softfloat-2a license unless specifically + * indicated otherwise. + */ + +/* +=============================================================================== +This C header file is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2a. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +#ifndef _SOFTFLOAT_HELPERS_H_ +#define _SOFTFLOAT_HELPERS_H_ + +#include "fpu/softfloat-types.h" + +static inline void set_float_detect_tininess(int val, float_status *status) +{ + status->float_detect_tininess = val; +} + +static inline void set_float_rounding_mode(int val, float_status *status) +{ + status->float_rounding_mode = val; +} + +static inline void set_float_exception_flags(int val, float_status *status) +{ + status->float_exception_flags = val; +} + +static inline void set_floatx80_rounding_precision(int val, + float_status *status) +{ + status->floatx80_rounding_precision = val; +} + +static inline void set_flush_to_zero(flag val, float_status *status) +{ + status->flush_to_zero = val; +} + +static inline void set_flush_inputs_to_zero(flag val, float_status *status) +{ + status->flush_inputs_to_zero = val; +} + +static inline void set_default_nan_mode(flag val, float_status *status) +{ + status->default_nan_mode = val; +} + +static inline void set_snan_bit_is_one(flag val, float_status *status) +{ + status->snan_bit_is_one = val; +} + +static inline int get_float_detect_tininess(float_status *status) +{ + return status->float_detect_tininess; +} + +static inline int get_float_rounding_mode(float_status *status) +{ + return status->float_rounding_mode; +} + +static inline int get_float_exception_flags(float_status *status) +{ + return status->float_exception_flags; +} + +static inline int get_floatx80_rounding_precision(float_status *status) +{ + return status->floatx80_rounding_precision; +} + +static inline flag get_flush_to_zero(float_status *status) +{ + return status->flush_to_zero; +} + +static inline flag get_flush_inputs_to_zero(float_status *status) +{ + return status->flush_inputs_to_zero; +} + +static inline flag get_default_nan_mode(float_status *status) +{ + return status->default_nan_mode; +} + +#endif /* _SOFTFLOAT_HELPERS_H_ */ diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index d9333eb..ecb8ba0 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -93,68 +93,7 @@ enum { }; #include "fpu/softfloat-types.h" - -static inline void set_float_detect_tininess(int val, float_status *status) -{ - status->float_detect_tininess = val; -} -static inline void set_float_rounding_mode(int val, float_status *status) -{ - status->float_rounding_mode = val; -} -static inline void set_float_exception_flags(int val, float_status *status) -{ - status->float_exception_flags = val; -} -static inline void set_floatx80_rounding_precision(int val, - float_status *status) -{ - status->floatx80_rounding_precision = val; -} -static inline void set_flush_to_zero(flag val, float_status *status) -{ - status->flush_to_zero = val; -} -static inline void set_flush_inputs_to_zero(flag val, float_status *status) -{ - status->flush_inputs_to_zero = val; -} -static inline void set_default_nan_mode(flag val, float_status *status) -{ - status->default_nan_mode = val; -} -static inline void set_snan_bit_is_one(flag val, float_status *status) -{ - status->snan_bit_is_one = val; -} -static inline int get_float_detect_tininess(float_status *status) -{ - return status->float_detect_tininess; -} -static inline int get_float_rounding_mode(float_status *status) -{ - return status->float_rounding_mode; -} -static inline int get_float_exception_flags(float_status *status) -{ - return status->float_exception_flags; -} -static inline int get_floatx80_rounding_precision(float_status *status) -{ - return status->floatx80_rounding_precision; -} -static inline flag get_flush_to_zero(float_status *status) -{ - return status->flush_to_zero; -} -static inline flag get_flush_inputs_to_zero(float_status *status) -{ - return status->flush_inputs_to_zero; -} -static inline flag get_default_nan_mode(float_status *status) -{ - return status->default_nan_mode; -} +#include "fpu/softfloat-helpers.h" /*---------------------------------------------------------------------------- | Routine to raise any or all of the software IEC/IEEE floating-point -- cgit v1.1 From 5937fb63a92d54cc4e5270256e4387c4d3a70091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 8 Aug 2019 17:05:15 +0100 Subject: fpu: make softfloat-macros "self-contained" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The macros use the "flags" type and to be consistent if anyone just needs the macros we should bring in the header we need. There is an outstanding TODO to audit the use of "flags" and replace with bool at which point this include could be dropped. Signed-off-by: Alex Bennée Acked-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé --- include/fpu/softfloat-macros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fpu/softfloat-macros.h b/include/fpu/softfloat-macros.h index 3a95673..605c4f4 100644 --- a/include/fpu/softfloat-macros.h +++ b/include/fpu/softfloat-macros.h @@ -82,7 +82,7 @@ this code that are retained. #ifndef FPU_SOFTFLOAT_MACROS_H #define FPU_SOFTFLOAT_MACROS_H -#include "fpu/softfloat.h" +#include "fpu/softfloat-types.h" /*---------------------------------------------------------------------------- | Shifts `a' right by the number of bits given in `count'. If any nonzero -- cgit v1.1 From 00f43279a3e5e7ea3a0fa853157863663e838e2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 8 Aug 2019 17:18:21 +0100 Subject: fpu: rename softfloat-specialize.h -> .inc.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is not a normal header and should only be included in the main softfloat.c file to bring in the various target specific specialisations. Indeed as it contains non-inlined C functions it is not even a legal header. Rename it to match our included C convention. Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé --- fpu/softfloat-specialize.h | 1083 ---------------------------------------- fpu/softfloat-specialize.inc.c | 1083 ++++++++++++++++++++++++++++++++++++++++ fpu/softfloat.c | 2 +- 3 files changed, 1084 insertions(+), 1084 deletions(-) delete mode 100644 fpu/softfloat-specialize.h create mode 100644 fpu/softfloat-specialize.inc.c diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h deleted file mode 100644 index 5ab2fa1..0000000 --- a/fpu/softfloat-specialize.h +++ /dev/null @@ -1,1083 +0,0 @@ -/* - * QEMU float support - * - * The code in this source file is derived from release 2a of the SoftFloat - * IEC/IEEE Floating-point Arithmetic Package. Those parts of the code (and - * some later contributions) are provided under that license, as detailed below. - * It has subsequently been modified by contributors to the QEMU Project, - * so some portions are provided under: - * the SoftFloat-2a license - * the BSD license - * GPL-v2-or-later - * - * Any future contributions to this file after December 1st 2014 will be - * taken to be licensed under the Softfloat-2a license unless specifically - * indicated otherwise. - */ - -/* -=============================================================================== -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2a. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort -has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT -TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO -PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY -AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) they include prominent notice that the work is derivative, and (2) they -include prominent notice akin to these four paragraphs for those parts of -this code that are retained. - -=============================================================================== -*/ - -/* BSD licensing: - * Copyright (c) 2006, Fabrice Bellard - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* Portions of this work are licensed under the terms of the GNU GPL, - * version 2 or later. See the COPYING file in the top-level directory. - */ - -/* Define for architectures which deviate from IEEE in not supporting - * signaling NaNs (so all NaNs are treated as quiet). - */ -#if defined(TARGET_XTENSA) -#define NO_SIGNALING_NANS 1 -#endif - -/* Define how the architecture discriminates signaling NaNs. - * This done with the most significant bit of the fraction. - * In IEEE 754-1985 this was implementation defined, but in IEEE 754-2008 - * the msb must be zero. MIPS is (so far) unique in supporting both the - * 2008 revision and backward compatibility with their original choice. - * Thus for MIPS we must make the choice at runtime. - */ -static inline flag snan_bit_is_one(float_status *status) -{ -#if defined(TARGET_MIPS) - return status->snan_bit_is_one; -#elif defined(TARGET_HPPA) || defined(TARGET_UNICORE32) || defined(TARGET_SH4) - return 1; -#else - return 0; -#endif -} - -/*---------------------------------------------------------------------------- -| For the deconstructed floating-point with fraction FRAC, return true -| if the fraction represents a signalling NaN; otherwise false. -*----------------------------------------------------------------------------*/ - -static bool parts_is_snan_frac(uint64_t frac, float_status *status) -{ -#ifdef NO_SIGNALING_NANS - return false; -#else - flag msb = extract64(frac, DECOMPOSED_BINARY_POINT - 1, 1); - return msb == snan_bit_is_one(status); -#endif -} - -/*---------------------------------------------------------------------------- -| The pattern for a default generated deconstructed floating-point NaN. -*----------------------------------------------------------------------------*/ - -static FloatParts parts_default_nan(float_status *status) -{ - bool sign = 0; - uint64_t frac; - -#if defined(TARGET_SPARC) || defined(TARGET_M68K) - /* !snan_bit_is_one, set all bits */ - frac = (1ULL << DECOMPOSED_BINARY_POINT) - 1; -#elif defined(TARGET_I386) || defined(TARGET_X86_64) \ - || defined(TARGET_MICROBLAZE) - /* !snan_bit_is_one, set sign and msb */ - frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1); - sign = 1; -#elif defined(TARGET_HPPA) - /* snan_bit_is_one, set msb-1. */ - frac = 1ULL << (DECOMPOSED_BINARY_POINT - 2); -#else - /* This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V, - * S390, SH4, TriCore, and Xtensa. I cannot find documentation - * for Unicore32; the choice from the original commit is unchanged. - * Our other supported targets, CRIS, LM32, Moxie, Nios2, and Tile, - * do not have floating-point. - */ - if (snan_bit_is_one(status)) { - /* set all bits other than msb */ - frac = (1ULL << (DECOMPOSED_BINARY_POINT - 1)) - 1; - } else { - /* set msb */ - frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1); - } -#endif - - return (FloatParts) { - .cls = float_class_qnan, - .sign = sign, - .exp = INT_MAX, - .frac = frac - }; -} - -/*---------------------------------------------------------------------------- -| Returns a quiet NaN from a signalling NaN for the deconstructed -| floating-point parts. -*----------------------------------------------------------------------------*/ - -static FloatParts parts_silence_nan(FloatParts a, float_status *status) -{ -#ifdef NO_SIGNALING_NANS - g_assert_not_reached(); -#elif defined(TARGET_HPPA) - a.frac &= ~(1ULL << (DECOMPOSED_BINARY_POINT - 1)); - a.frac |= 1ULL << (DECOMPOSED_BINARY_POINT - 2); -#else - if (snan_bit_is_one(status)) { - return parts_default_nan(status); - } else { - a.frac |= 1ULL << (DECOMPOSED_BINARY_POINT - 1); - } -#endif - a.cls = float_class_qnan; - return a; -} - -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. -*----------------------------------------------------------------------------*/ -floatx80 floatx80_default_nan(float_status *status) -{ - floatx80 r; - - /* None of the targets that have snan_bit_is_one use floatx80. */ - assert(!snan_bit_is_one(status)); -#if defined(TARGET_M68K) - r.low = UINT64_C(0xFFFFFFFFFFFFFFFF); - r.high = 0x7FFF; -#else - /* X86 */ - r.low = UINT64_C(0xC000000000000000); - r.high = 0xFFFF; -#endif - return r; -} - -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision inf. -*----------------------------------------------------------------------------*/ - -#define floatx80_infinity_high 0x7FFF -#if defined(TARGET_M68K) -#define floatx80_infinity_low UINT64_C(0x0000000000000000) -#else -#define floatx80_infinity_low UINT64_C(0x8000000000000000) -#endif - -const floatx80 floatx80_infinity - = make_floatx80_init(floatx80_infinity_high, floatx80_infinity_low); - -/*---------------------------------------------------------------------------- -| Raises the exceptions specified by `flags'. Floating-point traps can be -| defined here if desired. It is currently not possible for such a trap -| to substitute a result value. If traps are not implemented, this routine -| should be simply `float_exception_flags |= flags;'. -*----------------------------------------------------------------------------*/ - -void float_raise(uint8_t flags, float_status *status) -{ - status->float_exception_flags |= flags; -} - -/*---------------------------------------------------------------------------- -| Internal canonical NaN format. -*----------------------------------------------------------------------------*/ -typedef struct { - flag sign; - uint64_t high, low; -} commonNaNT; - -/*---------------------------------------------------------------------------- -| Returns 1 if the half-precision floating-point value `a' is a quiet -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -int float16_is_quiet_nan(float16 a_, float_status *status) -{ -#ifdef NO_SIGNALING_NANS - return float16_is_any_nan(a_); -#else - uint16_t a = float16_val(a_); - if (snan_bit_is_one(status)) { - 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_, float_status *status) -{ -#ifdef NO_SIGNALING_NANS - return 0; -#else - uint16_t a = float16_val(a_); - if (snan_bit_is_one(status)) { - return ((a & ~0x8000) >= 0x7C80); - } else { - return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF); - } -#endif -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a quiet -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -int float32_is_quiet_nan(float32 a_, float_status *status) -{ -#ifdef NO_SIGNALING_NANS - return float32_is_any_nan(a_); -#else - uint32_t a = float32_val(a_); - if (snan_bit_is_one(status)) { - return (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF); - } else { - return ((uint32_t)(a << 1) >= 0xFF800000); - } -#endif -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -int float32_is_signaling_nan(float32 a_, float_status *status) -{ -#ifdef NO_SIGNALING_NANS - return 0; -#else - uint32_t a = float32_val(a_); - if (snan_bit_is_one(status)) { - return ((uint32_t)(a << 1) >= 0xFF800000); - } else { - return (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF); - } -#endif -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT float32ToCommonNaN(float32 a, float_status *status) -{ - commonNaNT z; - - if (float32_is_signaling_nan(a, status)) { - float_raise(float_flag_invalid, status); - } - z.sign = float32_val(a) >> 31; - z.low = 0; - z.high = ((uint64_t)float32_val(a)) << 41; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the single- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float32 commonNaNToFloat32(commonNaNT a, float_status *status) -{ - uint32_t mantissa = a.high >> 41; - - if (status->default_nan_mode) { - return float32_default_nan(status); - } - - if (mantissa) { - return make_float32( - (((uint32_t)a.sign) << 31) | 0x7F800000 | (a.high >> 41)); - } else { - return float32_default_nan(status); - } -} - -/*---------------------------------------------------------------------------- -| Select which NaN to propagate for a two-input operation. -| IEEE754 doesn't specify all the details of this, so the -| algorithm is target-specific. -| The routine is passed various bits of information about the -| two NaNs and should return 0 to select NaN a and 1 for NaN b. -| Note that signalling NaNs are always squashed to quiet NaNs -| by the caller, by calling floatXX_silence_nan() before -| returning them. -| -| aIsLargerSignificand is only valid if both a and b are NaNs -| of some kind, and is true if a has the larger significand, -| or if both a and b have the same significand but a is -| positive but b is negative. It is only needed for the x87 -| tie-break rule. -*----------------------------------------------------------------------------*/ - -static int pickNaN(FloatClass a_cls, FloatClass b_cls, - flag aIsLargerSignificand) -{ -#if defined(TARGET_ARM) || defined(TARGET_MIPS) || defined(TARGET_HPPA) - /* ARM mandated NaN propagation rules (see FPProcessNaNs()), take - * the first of: - * 1. A if it is signaling - * 2. B if it is signaling - * 3. A (quiet) - * 4. B (quiet) - * A signaling NaN is always quietened before returning it. - */ - /* According to MIPS specifications, if one of the two operands is - * a sNaN, a new qNaN has to be generated. This is done in - * floatXX_silence_nan(). For qNaN inputs the specifications - * says: "When possible, this QNaN result is one of the operand QNaN - * values." In practice it seems that most implementations choose - * the first operand if both operands are qNaN. In short this gives - * the following rules: - * 1. A if it is signaling - * 2. B if it is signaling - * 3. A (quiet) - * 4. B (quiet) - * A signaling NaN is always silenced before returning it. - */ - if (is_snan(a_cls)) { - return 0; - } else if (is_snan(b_cls)) { - return 1; - } else if (is_qnan(a_cls)) { - return 0; - } else { - return 1; - } -#elif defined(TARGET_PPC) || defined(TARGET_XTENSA) || defined(TARGET_M68K) - /* PowerPC propagation rules: - * 1. A if it sNaN or qNaN - * 2. B if it sNaN or qNaN - * A signaling NaN is always silenced before returning it. - */ - /* M68000 FAMILY PROGRAMMER'S REFERENCE MANUAL - * 3.4 FLOATING-POINT INSTRUCTION DETAILS - * If either operand, but not both operands, of an operation is a - * nonsignaling NaN, then that NaN is returned as the result. If both - * operands are nonsignaling NaNs, then the destination operand - * nonsignaling NaN is returned as the result. - * If either operand to an operation is a signaling NaN (SNaN), then the - * SNaN bit is set in the FPSR EXC byte. If the SNaN exception enable bit - * is set in the FPCR ENABLE byte, then the exception is taken and the - * destination is not modified. If the SNaN exception enable bit is not - * set, setting the SNaN bit in the operand to a one converts the SNaN to - * a nonsignaling NaN. The operation then continues as described in the - * preceding paragraph for nonsignaling NaNs. - */ - if (is_nan(a_cls)) { - return 0; - } else { - return 1; - } -#else - /* This implements x87 NaN propagation rules: - * SNaN + QNaN => return the QNaN - * two SNaNs => return the one with the larger significand, silenced - * two QNaNs => return the one with the larger significand - * SNaN and a non-NaN => return the SNaN, silenced - * QNaN and a non-NaN => return the QNaN - * - * If we get down to comparing significands and they are the same, - * return the NaN with the positive sign bit (if any). - */ - if (is_snan(a_cls)) { - if (is_snan(b_cls)) { - return aIsLargerSignificand ? 0 : 1; - } - return is_qnan(b_cls) ? 1 : 0; - } else if (is_qnan(a_cls)) { - if (is_snan(b_cls) || !is_qnan(b_cls)) { - return 0; - } else { - return aIsLargerSignificand ? 0 : 1; - } - } else { - return 1; - } -#endif -} - -/*---------------------------------------------------------------------------- -| Select which NaN to propagate for a three-input operation. -| For the moment we assume that no CPU needs the 'larger significand' -| information. -| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN -*----------------------------------------------------------------------------*/ -static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls, - bool infzero, float_status *status) -{ -#if defined(TARGET_ARM) - /* For ARM, the (inf,zero,qnan) case sets InvalidOp and returns - * the default NaN - */ - if (infzero && is_qnan(c_cls)) { - float_raise(float_flag_invalid, status); - return 3; - } - - /* This looks different from the ARM ARM pseudocode, because the ARM ARM - * puts the operands to a fused mac operation (a*b)+c in the order c,a,b. - */ - if (is_snan(c_cls)) { - return 2; - } else if (is_snan(a_cls)) { - return 0; - } else if (is_snan(b_cls)) { - return 1; - } else if (is_qnan(c_cls)) { - return 2; - } else if (is_qnan(a_cls)) { - return 0; - } else { - return 1; - } -#elif defined(TARGET_MIPS) - if (snan_bit_is_one(status)) { - /* - * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan) - * case sets InvalidOp and returns the default NaN - */ - if (infzero) { - float_raise(float_flag_invalid, status); - return 3; - } - /* Prefer sNaN over qNaN, in the a, b, c order. */ - if (is_snan(a_cls)) { - return 0; - } else if (is_snan(b_cls)) { - return 1; - } else if (is_snan(c_cls)) { - return 2; - } else if (is_qnan(a_cls)) { - return 0; - } else if (is_qnan(b_cls)) { - return 1; - } else { - return 2; - } - } else { - /* - * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan) - * case sets InvalidOp and returns the input value 'c' - */ - if (infzero) { - float_raise(float_flag_invalid, status); - return 2; - } - /* Prefer sNaN over qNaN, in the c, a, b order. */ - if (is_snan(c_cls)) { - return 2; - } else if (is_snan(a_cls)) { - return 0; - } else if (is_snan(b_cls)) { - return 1; - } else if (is_qnan(c_cls)) { - return 2; - } else if (is_qnan(a_cls)) { - return 0; - } else { - return 1; - } - } -#elif defined(TARGET_PPC) - /* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer - * to return an input NaN if we have one (ie c) rather than generating - * a default NaN - */ - if (infzero) { - float_raise(float_flag_invalid, status); - return 2; - } - - /* If fRA is a NaN return it; otherwise if fRB is a NaN return it; - * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB - */ - if (is_nan(a_cls)) { - return 0; - } else if (is_nan(c_cls)) { - return 2; - } else { - return 1; - } -#else - /* A default implementation: prefer a to b to c. - * This is unlikely to actually match any real implementation. - */ - if (is_nan(a_cls)) { - return 0; - } else if (is_nan(b_cls)) { - return 1; - } else { - return 2; - } -#endif -} - -/*---------------------------------------------------------------------------- -| Takes two single-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static float32 propagateFloat32NaN(float32 a, float32 b, float_status *status) -{ - flag aIsLargerSignificand; - uint32_t av, bv; - FloatClass a_cls, b_cls; - - /* This is not complete, but is good enough for pickNaN. */ - a_cls = (!float32_is_any_nan(a) - ? float_class_normal - : float32_is_signaling_nan(a, status) - ? float_class_snan - : float_class_qnan); - b_cls = (!float32_is_any_nan(b) - ? float_class_normal - : float32_is_signaling_nan(b, status) - ? float_class_snan - : float_class_qnan); - - av = float32_val(a); - bv = float32_val(b); - - if (is_snan(a_cls) || is_snan(b_cls)) { - float_raise(float_flag_invalid, status); - } - - if (status->default_nan_mode) { - return float32_default_nan(status); - } - - if ((uint32_t)(av << 1) < (uint32_t)(bv << 1)) { - aIsLargerSignificand = 0; - } else if ((uint32_t)(bv << 1) < (uint32_t)(av << 1)) { - aIsLargerSignificand = 1; - } else { - aIsLargerSignificand = (av < bv) ? 1 : 0; - } - - if (pickNaN(a_cls, b_cls, aIsLargerSignificand)) { - if (is_snan(b_cls)) { - return float32_silence_nan(b, status); - } - return b; - } else { - if (is_snan(a_cls)) { - return float32_silence_nan(a, status); - } - return a; - } -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a quiet -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -int float64_is_quiet_nan(float64 a_, float_status *status) -{ -#ifdef NO_SIGNALING_NANS - return float64_is_any_nan(a_); -#else - uint64_t a = float64_val(a_); - if (snan_bit_is_one(status)) { - return (((a >> 51) & 0xFFF) == 0xFFE) - && (a & 0x0007FFFFFFFFFFFFULL); - } else { - return ((a << 1) >= 0xFFF0000000000000ULL); - } -#endif -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -int float64_is_signaling_nan(float64 a_, float_status *status) -{ -#ifdef NO_SIGNALING_NANS - return 0; -#else - uint64_t a = float64_val(a_); - if (snan_bit_is_one(status)) { - return ((a << 1) >= 0xFFF0000000000000ULL); - } else { - return (((a >> 51) & 0xFFF) == 0xFFE) - && (a & UINT64_C(0x0007FFFFFFFFFFFF)); - } -#endif -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT float64ToCommonNaN(float64 a, float_status *status) -{ - commonNaNT z; - - if (float64_is_signaling_nan(a, status)) { - float_raise(float_flag_invalid, status); - } - z.sign = float64_val(a) >> 63; - z.low = 0; - z.high = float64_val(a) << 12; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the double- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float64 commonNaNToFloat64(commonNaNT a, float_status *status) -{ - uint64_t mantissa = a.high >> 12; - - if (status->default_nan_mode) { - return float64_default_nan(status); - } - - if (mantissa) { - return make_float64( - (((uint64_t) a.sign) << 63) - | UINT64_C(0x7FF0000000000000) - | (a.high >> 12)); - } else { - return float64_default_nan(status); - } -} - -/*---------------------------------------------------------------------------- -| Takes two double-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static float64 propagateFloat64NaN(float64 a, float64 b, float_status *status) -{ - flag aIsLargerSignificand; - uint64_t av, bv; - FloatClass a_cls, b_cls; - - /* This is not complete, but is good enough for pickNaN. */ - a_cls = (!float64_is_any_nan(a) - ? float_class_normal - : float64_is_signaling_nan(a, status) - ? float_class_snan - : float_class_qnan); - b_cls = (!float64_is_any_nan(b) - ? float_class_normal - : float64_is_signaling_nan(b, status) - ? float_class_snan - : float_class_qnan); - - av = float64_val(a); - bv = float64_val(b); - - if (is_snan(a_cls) || is_snan(b_cls)) { - float_raise(float_flag_invalid, status); - } - - if (status->default_nan_mode) { - return float64_default_nan(status); - } - - if ((uint64_t)(av << 1) < (uint64_t)(bv << 1)) { - aIsLargerSignificand = 0; - } else if ((uint64_t)(bv << 1) < (uint64_t)(av << 1)) { - aIsLargerSignificand = 1; - } else { - aIsLargerSignificand = (av < bv) ? 1 : 0; - } - - if (pickNaN(a_cls, b_cls, aIsLargerSignificand)) { - if (is_snan(b_cls)) { - return float64_silence_nan(b, status); - } - return b; - } else { - if (is_snan(a_cls)) { - return float64_silence_nan(a, status); - } - return a; - } -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is a -| quiet NaN; otherwise returns 0. This slightly differs from the same -| function for other types as floatx80 has an explicit bit. -*----------------------------------------------------------------------------*/ - -int floatx80_is_quiet_nan(floatx80 a, float_status *status) -{ -#ifdef NO_SIGNALING_NANS - return floatx80_is_any_nan(a); -#else - if (snan_bit_is_one(status)) { - uint64_t aLow; - - aLow = a.low & ~0x4000000000000000ULL; - return ((a.high & 0x7FFF) == 0x7FFF) - && (aLow << 1) - && (a.low == aLow); - } else { - return ((a.high & 0x7FFF) == 0x7FFF) - && (UINT64_C(0x8000000000000000) <= ((uint64_t)(a.low << 1))); - } -#endif -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is a -| signaling NaN; otherwise returns 0. This slightly differs from the same -| function for other types as floatx80 has an explicit bit. -*----------------------------------------------------------------------------*/ - -int floatx80_is_signaling_nan(floatx80 a, float_status *status) -{ -#ifdef NO_SIGNALING_NANS - return 0; -#else - if (snan_bit_is_one(status)) { - return ((a.high & 0x7FFF) == 0x7FFF) - && ((a.low << 1) >= 0x8000000000000000ULL); - } else { - uint64_t aLow; - - aLow = a.low & ~UINT64_C(0x4000000000000000); - return ((a.high & 0x7FFF) == 0x7FFF) - && (uint64_t)(aLow << 1) - && (a.low == aLow); - } -#endif -} - -/*---------------------------------------------------------------------------- -| Returns a quiet NaN from a signalling NaN for the extended double-precision -| floating point value `a'. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_silence_nan(floatx80 a, float_status *status) -{ - /* None of the targets that have snan_bit_is_one use floatx80. */ - assert(!snan_bit_is_one(status)); - a.low |= UINT64_C(0xC000000000000000); - return a; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the -| invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT floatx80ToCommonNaN(floatx80 a, float_status *status) -{ - floatx80 dflt; - commonNaNT z; - - if (floatx80_is_signaling_nan(a, status)) { - float_raise(float_flag_invalid, status); - } - if (a.low >> 63) { - z.sign = a.high >> 15; - z.low = 0; - z.high = a.low << 1; - } else { - dflt = floatx80_default_nan(status); - z.sign = dflt.high >> 15; - z.low = 0; - z.high = dflt.low << 1; - } - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the extended -| double-precision floating-point format. -*----------------------------------------------------------------------------*/ - -static floatx80 commonNaNToFloatx80(commonNaNT a, float_status *status) -{ - floatx80 z; - - if (status->default_nan_mode) { - return floatx80_default_nan(status); - } - - if (a.high >> 1) { - z.low = UINT64_C(0x8000000000000000) | a.high >> 1; - z.high = (((uint16_t)a.sign) << 15) | 0x7FFF; - } else { - z = floatx80_default_nan(status); - } - return z; -} - -/*---------------------------------------------------------------------------- -| Takes two extended double-precision floating-point values `a' and `b', one -| of which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status) -{ - flag aIsLargerSignificand; - FloatClass a_cls, b_cls; - - /* This is not complete, but is good enough for pickNaN. */ - a_cls = (!floatx80_is_any_nan(a) - ? float_class_normal - : floatx80_is_signaling_nan(a, status) - ? float_class_snan - : float_class_qnan); - b_cls = (!floatx80_is_any_nan(b) - ? float_class_normal - : floatx80_is_signaling_nan(b, status) - ? float_class_snan - : float_class_qnan); - - if (is_snan(a_cls) || is_snan(b_cls)) { - float_raise(float_flag_invalid, status); - } - - if (status->default_nan_mode) { - return floatx80_default_nan(status); - } - - if (a.low < b.low) { - aIsLargerSignificand = 0; - } else if (b.low < a.low) { - aIsLargerSignificand = 1; - } else { - aIsLargerSignificand = (a.high < b.high) ? 1 : 0; - } - - if (pickNaN(a_cls, b_cls, aIsLargerSignificand)) { - if (is_snan(b_cls)) { - return floatx80_silence_nan(b, status); - } - return b; - } else { - if (is_snan(a_cls)) { - return floatx80_silence_nan(a, status); - } - return a; - } -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a quiet -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -int float128_is_quiet_nan(float128 a, float_status *status) -{ -#ifdef NO_SIGNALING_NANS - return float128_is_any_nan(a); -#else - if (snan_bit_is_one(status)) { - return (((a.high >> 47) & 0xFFFF) == 0xFFFE) - && (a.low || (a.high & 0x00007FFFFFFFFFFFULL)); - } else { - return ((a.high << 1) >= 0xFFFF000000000000ULL) - && (a.low || (a.high & 0x0000FFFFFFFFFFFFULL)); - } -#endif -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a -| signaling NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -int float128_is_signaling_nan(float128 a, float_status *status) -{ -#ifdef NO_SIGNALING_NANS - return 0; -#else - if (snan_bit_is_one(status)) { - return ((a.high << 1) >= 0xFFFF000000000000ULL) - && (a.low || (a.high & 0x0000FFFFFFFFFFFFULL)); - } else { - return (((a.high >> 47) & 0xFFFF) == 0xFFFE) - && (a.low || (a.high & UINT64_C(0x00007FFFFFFFFFFF))); - } -#endif -} - -/*---------------------------------------------------------------------------- -| Returns a quiet NaN from a signalling NaN for the quadruple-precision -| floating point value `a'. -*----------------------------------------------------------------------------*/ - -float128 float128_silence_nan(float128 a, float_status *status) -{ -#ifdef NO_SIGNALING_NANS - g_assert_not_reached(); -#else - if (snan_bit_is_one(status)) { - return float128_default_nan(status); - } else { - a.high |= UINT64_C(0x0000800000000000); - return a; - } -#endif -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT float128ToCommonNaN(float128 a, float_status *status) -{ - commonNaNT z; - - if (float128_is_signaling_nan(a, status)) { - float_raise(float_flag_invalid, status); - } - z.sign = a.high >> 63; - shortShift128Left(a.high, a.low, 16, &z.high, &z.low); - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the quadruple- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float128 commonNaNToFloat128(commonNaNT a, float_status *status) -{ - float128 z; - - if (status->default_nan_mode) { - return float128_default_nan(status); - } - - shift128Right(a.high, a.low, 16, &z.high, &z.low); - z.high |= (((uint64_t)a.sign) << 63) | UINT64_C(0x7FFF000000000000); - return z; -} - -/*---------------------------------------------------------------------------- -| Takes two quadruple-precision floating-point values `a' and `b', one of -| which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static float128 propagateFloat128NaN(float128 a, float128 b, - float_status *status) -{ - flag aIsLargerSignificand; - FloatClass a_cls, b_cls; - - /* This is not complete, but is good enough for pickNaN. */ - a_cls = (!float128_is_any_nan(a) - ? float_class_normal - : float128_is_signaling_nan(a, status) - ? float_class_snan - : float_class_qnan); - b_cls = (!float128_is_any_nan(b) - ? float_class_normal - : float128_is_signaling_nan(b, status) - ? float_class_snan - : float_class_qnan); - - if (is_snan(a_cls) || is_snan(b_cls)) { - float_raise(float_flag_invalid, status); - } - - if (status->default_nan_mode) { - return float128_default_nan(status); - } - - if (lt128(a.high << 1, a.low, b.high << 1, b.low)) { - aIsLargerSignificand = 0; - } else if (lt128(b.high << 1, b.low, a.high << 1, a.low)) { - aIsLargerSignificand = 1; - } else { - aIsLargerSignificand = (a.high < b.high) ? 1 : 0; - } - - if (pickNaN(a_cls, b_cls, aIsLargerSignificand)) { - if (is_snan(b_cls)) { - return float128_silence_nan(b, status); - } - return b; - } else { - if (is_snan(a_cls)) { - return float128_silence_nan(a, status); - } - return a; - } -} diff --git a/fpu/softfloat-specialize.inc.c b/fpu/softfloat-specialize.inc.c new file mode 100644 index 0000000..5ab2fa1 --- /dev/null +++ b/fpu/softfloat-specialize.inc.c @@ -0,0 +1,1083 @@ +/* + * QEMU float support + * + * The code in this source file is derived from release 2a of the SoftFloat + * IEC/IEEE Floating-point Arithmetic Package. Those parts of the code (and + * some later contributions) are provided under that license, as detailed below. + * It has subsequently been modified by contributors to the QEMU Project, + * so some portions are provided under: + * the SoftFloat-2a license + * the BSD license + * GPL-v2-or-later + * + * Any future contributions to this file after December 1st 2014 will be + * taken to be licensed under the Softfloat-2a license unless specifically + * indicated otherwise. + */ + +/* +=============================================================================== +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2a. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +/* BSD licensing: + * Copyright (c) 2006, Fabrice Bellard + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Portions of this work are licensed under the terms of the GNU GPL, + * version 2 or later. See the COPYING file in the top-level directory. + */ + +/* Define for architectures which deviate from IEEE in not supporting + * signaling NaNs (so all NaNs are treated as quiet). + */ +#if defined(TARGET_XTENSA) +#define NO_SIGNALING_NANS 1 +#endif + +/* Define how the architecture discriminates signaling NaNs. + * This done with the most significant bit of the fraction. + * In IEEE 754-1985 this was implementation defined, but in IEEE 754-2008 + * the msb must be zero. MIPS is (so far) unique in supporting both the + * 2008 revision and backward compatibility with their original choice. + * Thus for MIPS we must make the choice at runtime. + */ +static inline flag snan_bit_is_one(float_status *status) +{ +#if defined(TARGET_MIPS) + return status->snan_bit_is_one; +#elif defined(TARGET_HPPA) || defined(TARGET_UNICORE32) || defined(TARGET_SH4) + return 1; +#else + return 0; +#endif +} + +/*---------------------------------------------------------------------------- +| For the deconstructed floating-point with fraction FRAC, return true +| if the fraction represents a signalling NaN; otherwise false. +*----------------------------------------------------------------------------*/ + +static bool parts_is_snan_frac(uint64_t frac, float_status *status) +{ +#ifdef NO_SIGNALING_NANS + return false; +#else + flag msb = extract64(frac, DECOMPOSED_BINARY_POINT - 1, 1); + return msb == snan_bit_is_one(status); +#endif +} + +/*---------------------------------------------------------------------------- +| The pattern for a default generated deconstructed floating-point NaN. +*----------------------------------------------------------------------------*/ + +static FloatParts parts_default_nan(float_status *status) +{ + bool sign = 0; + uint64_t frac; + +#if defined(TARGET_SPARC) || defined(TARGET_M68K) + /* !snan_bit_is_one, set all bits */ + frac = (1ULL << DECOMPOSED_BINARY_POINT) - 1; +#elif defined(TARGET_I386) || defined(TARGET_X86_64) \ + || defined(TARGET_MICROBLAZE) + /* !snan_bit_is_one, set sign and msb */ + frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1); + sign = 1; +#elif defined(TARGET_HPPA) + /* snan_bit_is_one, set msb-1. */ + frac = 1ULL << (DECOMPOSED_BINARY_POINT - 2); +#else + /* This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V, + * S390, SH4, TriCore, and Xtensa. I cannot find documentation + * for Unicore32; the choice from the original commit is unchanged. + * Our other supported targets, CRIS, LM32, Moxie, Nios2, and Tile, + * do not have floating-point. + */ + if (snan_bit_is_one(status)) { + /* set all bits other than msb */ + frac = (1ULL << (DECOMPOSED_BINARY_POINT - 1)) - 1; + } else { + /* set msb */ + frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1); + } +#endif + + return (FloatParts) { + .cls = float_class_qnan, + .sign = sign, + .exp = INT_MAX, + .frac = frac + }; +} + +/*---------------------------------------------------------------------------- +| Returns a quiet NaN from a signalling NaN for the deconstructed +| floating-point parts. +*----------------------------------------------------------------------------*/ + +static FloatParts parts_silence_nan(FloatParts a, float_status *status) +{ +#ifdef NO_SIGNALING_NANS + g_assert_not_reached(); +#elif defined(TARGET_HPPA) + a.frac &= ~(1ULL << (DECOMPOSED_BINARY_POINT - 1)); + a.frac |= 1ULL << (DECOMPOSED_BINARY_POINT - 2); +#else + if (snan_bit_is_one(status)) { + return parts_default_nan(status); + } else { + a.frac |= 1ULL << (DECOMPOSED_BINARY_POINT - 1); + } +#endif + a.cls = float_class_qnan; + return a; +} + +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ +floatx80 floatx80_default_nan(float_status *status) +{ + floatx80 r; + + /* None of the targets that have snan_bit_is_one use floatx80. */ + assert(!snan_bit_is_one(status)); +#if defined(TARGET_M68K) + r.low = UINT64_C(0xFFFFFFFFFFFFFFFF); + r.high = 0x7FFF; +#else + /* X86 */ + r.low = UINT64_C(0xC000000000000000); + r.high = 0xFFFF; +#endif + return r; +} + +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision inf. +*----------------------------------------------------------------------------*/ + +#define floatx80_infinity_high 0x7FFF +#if defined(TARGET_M68K) +#define floatx80_infinity_low UINT64_C(0x0000000000000000) +#else +#define floatx80_infinity_low UINT64_C(0x8000000000000000) +#endif + +const floatx80 floatx80_infinity + = make_floatx80_init(floatx80_infinity_high, floatx80_infinity_low); + +/*---------------------------------------------------------------------------- +| Raises the exceptions specified by `flags'. Floating-point traps can be +| defined here if desired. It is currently not possible for such a trap +| to substitute a result value. If traps are not implemented, this routine +| should be simply `float_exception_flags |= flags;'. +*----------------------------------------------------------------------------*/ + +void float_raise(uint8_t flags, float_status *status) +{ + status->float_exception_flags |= flags; +} + +/*---------------------------------------------------------------------------- +| Internal canonical NaN format. +*----------------------------------------------------------------------------*/ +typedef struct { + flag sign; + uint64_t high, low; +} commonNaNT; + +/*---------------------------------------------------------------------------- +| Returns 1 if the half-precision floating-point value `a' is a quiet +| NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +int float16_is_quiet_nan(float16 a_, float_status *status) +{ +#ifdef NO_SIGNALING_NANS + return float16_is_any_nan(a_); +#else + uint16_t a = float16_val(a_); + if (snan_bit_is_one(status)) { + 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_, float_status *status) +{ +#ifdef NO_SIGNALING_NANS + return 0; +#else + uint16_t a = float16_val(a_); + if (snan_bit_is_one(status)) { + return ((a & ~0x8000) >= 0x7C80); + } else { + return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF); + } +#endif +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is a quiet +| NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +int float32_is_quiet_nan(float32 a_, float_status *status) +{ +#ifdef NO_SIGNALING_NANS + return float32_is_any_nan(a_); +#else + uint32_t a = float32_val(a_); + if (snan_bit_is_one(status)) { + return (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF); + } else { + return ((uint32_t)(a << 1) >= 0xFF800000); + } +#endif +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is a signaling +| NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +int float32_is_signaling_nan(float32 a_, float_status *status) +{ +#ifdef NO_SIGNALING_NANS + return 0; +#else + uint32_t a = float32_val(a_); + if (snan_bit_is_one(status)) { + return ((uint32_t)(a << 1) >= 0xFF800000); + } else { + return (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF); + } +#endif +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point NaN +| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ + +static commonNaNT float32ToCommonNaN(float32 a, float_status *status) +{ + commonNaNT z; + + if (float32_is_signaling_nan(a, status)) { + float_raise(float_flag_invalid, status); + } + z.sign = float32_val(a) >> 31; + z.low = 0; + z.high = ((uint64_t)float32_val(a)) << 41; + return z; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the single- +| precision floating-point format. +*----------------------------------------------------------------------------*/ + +static float32 commonNaNToFloat32(commonNaNT a, float_status *status) +{ + uint32_t mantissa = a.high >> 41; + + if (status->default_nan_mode) { + return float32_default_nan(status); + } + + if (mantissa) { + return make_float32( + (((uint32_t)a.sign) << 31) | 0x7F800000 | (a.high >> 41)); + } else { + return float32_default_nan(status); + } +} + +/*---------------------------------------------------------------------------- +| Select which NaN to propagate for a two-input operation. +| IEEE754 doesn't specify all the details of this, so the +| algorithm is target-specific. +| The routine is passed various bits of information about the +| two NaNs and should return 0 to select NaN a and 1 for NaN b. +| Note that signalling NaNs are always squashed to quiet NaNs +| by the caller, by calling floatXX_silence_nan() before +| returning them. +| +| aIsLargerSignificand is only valid if both a and b are NaNs +| of some kind, and is true if a has the larger significand, +| or if both a and b have the same significand but a is +| positive but b is negative. It is only needed for the x87 +| tie-break rule. +*----------------------------------------------------------------------------*/ + +static int pickNaN(FloatClass a_cls, FloatClass b_cls, + flag aIsLargerSignificand) +{ +#if defined(TARGET_ARM) || defined(TARGET_MIPS) || defined(TARGET_HPPA) + /* ARM mandated NaN propagation rules (see FPProcessNaNs()), take + * the first of: + * 1. A if it is signaling + * 2. B if it is signaling + * 3. A (quiet) + * 4. B (quiet) + * A signaling NaN is always quietened before returning it. + */ + /* According to MIPS specifications, if one of the two operands is + * a sNaN, a new qNaN has to be generated. This is done in + * floatXX_silence_nan(). For qNaN inputs the specifications + * says: "When possible, this QNaN result is one of the operand QNaN + * values." In practice it seems that most implementations choose + * the first operand if both operands are qNaN. In short this gives + * the following rules: + * 1. A if it is signaling + * 2. B if it is signaling + * 3. A (quiet) + * 4. B (quiet) + * A signaling NaN is always silenced before returning it. + */ + if (is_snan(a_cls)) { + return 0; + } else if (is_snan(b_cls)) { + return 1; + } else if (is_qnan(a_cls)) { + return 0; + } else { + return 1; + } +#elif defined(TARGET_PPC) || defined(TARGET_XTENSA) || defined(TARGET_M68K) + /* PowerPC propagation rules: + * 1. A if it sNaN or qNaN + * 2. B if it sNaN or qNaN + * A signaling NaN is always silenced before returning it. + */ + /* M68000 FAMILY PROGRAMMER'S REFERENCE MANUAL + * 3.4 FLOATING-POINT INSTRUCTION DETAILS + * If either operand, but not both operands, of an operation is a + * nonsignaling NaN, then that NaN is returned as the result. If both + * operands are nonsignaling NaNs, then the destination operand + * nonsignaling NaN is returned as the result. + * If either operand to an operation is a signaling NaN (SNaN), then the + * SNaN bit is set in the FPSR EXC byte. If the SNaN exception enable bit + * is set in the FPCR ENABLE byte, then the exception is taken and the + * destination is not modified. If the SNaN exception enable bit is not + * set, setting the SNaN bit in the operand to a one converts the SNaN to + * a nonsignaling NaN. The operation then continues as described in the + * preceding paragraph for nonsignaling NaNs. + */ + if (is_nan(a_cls)) { + return 0; + } else { + return 1; + } +#else + /* This implements x87 NaN propagation rules: + * SNaN + QNaN => return the QNaN + * two SNaNs => return the one with the larger significand, silenced + * two QNaNs => return the one with the larger significand + * SNaN and a non-NaN => return the SNaN, silenced + * QNaN and a non-NaN => return the QNaN + * + * If we get down to comparing significands and they are the same, + * return the NaN with the positive sign bit (if any). + */ + if (is_snan(a_cls)) { + if (is_snan(b_cls)) { + return aIsLargerSignificand ? 0 : 1; + } + return is_qnan(b_cls) ? 1 : 0; + } else if (is_qnan(a_cls)) { + if (is_snan(b_cls) || !is_qnan(b_cls)) { + return 0; + } else { + return aIsLargerSignificand ? 0 : 1; + } + } else { + return 1; + } +#endif +} + +/*---------------------------------------------------------------------------- +| Select which NaN to propagate for a three-input operation. +| For the moment we assume that no CPU needs the 'larger significand' +| information. +| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN +*----------------------------------------------------------------------------*/ +static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls, + bool infzero, float_status *status) +{ +#if defined(TARGET_ARM) + /* For ARM, the (inf,zero,qnan) case sets InvalidOp and returns + * the default NaN + */ + if (infzero && is_qnan(c_cls)) { + float_raise(float_flag_invalid, status); + return 3; + } + + /* This looks different from the ARM ARM pseudocode, because the ARM ARM + * puts the operands to a fused mac operation (a*b)+c in the order c,a,b. + */ + if (is_snan(c_cls)) { + return 2; + } else if (is_snan(a_cls)) { + return 0; + } else if (is_snan(b_cls)) { + return 1; + } else if (is_qnan(c_cls)) { + return 2; + } else if (is_qnan(a_cls)) { + return 0; + } else { + return 1; + } +#elif defined(TARGET_MIPS) + if (snan_bit_is_one(status)) { + /* + * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan) + * case sets InvalidOp and returns the default NaN + */ + if (infzero) { + float_raise(float_flag_invalid, status); + return 3; + } + /* Prefer sNaN over qNaN, in the a, b, c order. */ + if (is_snan(a_cls)) { + return 0; + } else if (is_snan(b_cls)) { + return 1; + } else if (is_snan(c_cls)) { + return 2; + } else if (is_qnan(a_cls)) { + return 0; + } else if (is_qnan(b_cls)) { + return 1; + } else { + return 2; + } + } else { + /* + * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan) + * case sets InvalidOp and returns the input value 'c' + */ + if (infzero) { + float_raise(float_flag_invalid, status); + return 2; + } + /* Prefer sNaN over qNaN, in the c, a, b order. */ + if (is_snan(c_cls)) { + return 2; + } else if (is_snan(a_cls)) { + return 0; + } else if (is_snan(b_cls)) { + return 1; + } else if (is_qnan(c_cls)) { + return 2; + } else if (is_qnan(a_cls)) { + return 0; + } else { + return 1; + } + } +#elif defined(TARGET_PPC) + /* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer + * to return an input NaN if we have one (ie c) rather than generating + * a default NaN + */ + if (infzero) { + float_raise(float_flag_invalid, status); + return 2; + } + + /* If fRA is a NaN return it; otherwise if fRB is a NaN return it; + * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB + */ + if (is_nan(a_cls)) { + return 0; + } else if (is_nan(c_cls)) { + return 2; + } else { + return 1; + } +#else + /* A default implementation: prefer a to b to c. + * This is unlikely to actually match any real implementation. + */ + if (is_nan(a_cls)) { + return 0; + } else if (is_nan(b_cls)) { + return 1; + } else { + return 2; + } +#endif +} + +/*---------------------------------------------------------------------------- +| Takes two single-precision floating-point values `a' and `b', one of which +| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +static float32 propagateFloat32NaN(float32 a, float32 b, float_status *status) +{ + flag aIsLargerSignificand; + uint32_t av, bv; + FloatClass a_cls, b_cls; + + /* This is not complete, but is good enough for pickNaN. */ + a_cls = (!float32_is_any_nan(a) + ? float_class_normal + : float32_is_signaling_nan(a, status) + ? float_class_snan + : float_class_qnan); + b_cls = (!float32_is_any_nan(b) + ? float_class_normal + : float32_is_signaling_nan(b, status) + ? float_class_snan + : float_class_qnan); + + av = float32_val(a); + bv = float32_val(b); + + if (is_snan(a_cls) || is_snan(b_cls)) { + float_raise(float_flag_invalid, status); + } + + if (status->default_nan_mode) { + return float32_default_nan(status); + } + + if ((uint32_t)(av << 1) < (uint32_t)(bv << 1)) { + aIsLargerSignificand = 0; + } else if ((uint32_t)(bv << 1) < (uint32_t)(av << 1)) { + aIsLargerSignificand = 1; + } else { + aIsLargerSignificand = (av < bv) ? 1 : 0; + } + + if (pickNaN(a_cls, b_cls, aIsLargerSignificand)) { + if (is_snan(b_cls)) { + return float32_silence_nan(b, status); + } + return b; + } else { + if (is_snan(a_cls)) { + return float32_silence_nan(a, status); + } + return a; + } +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is a quiet +| NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +int float64_is_quiet_nan(float64 a_, float_status *status) +{ +#ifdef NO_SIGNALING_NANS + return float64_is_any_nan(a_); +#else + uint64_t a = float64_val(a_); + if (snan_bit_is_one(status)) { + return (((a >> 51) & 0xFFF) == 0xFFE) + && (a & 0x0007FFFFFFFFFFFFULL); + } else { + return ((a << 1) >= 0xFFF0000000000000ULL); + } +#endif +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is a signaling +| NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +int float64_is_signaling_nan(float64 a_, float_status *status) +{ +#ifdef NO_SIGNALING_NANS + return 0; +#else + uint64_t a = float64_val(a_); + if (snan_bit_is_one(status)) { + return ((a << 1) >= 0xFFF0000000000000ULL); + } else { + return (((a >> 51) & 0xFFF) == 0xFFE) + && (a & UINT64_C(0x0007FFFFFFFFFFFF)); + } +#endif +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point NaN +| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ + +static commonNaNT float64ToCommonNaN(float64 a, float_status *status) +{ + commonNaNT z; + + if (float64_is_signaling_nan(a, status)) { + float_raise(float_flag_invalid, status); + } + z.sign = float64_val(a) >> 63; + z.low = 0; + z.high = float64_val(a) << 12; + return z; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the double- +| precision floating-point format. +*----------------------------------------------------------------------------*/ + +static float64 commonNaNToFloat64(commonNaNT a, float_status *status) +{ + uint64_t mantissa = a.high >> 12; + + if (status->default_nan_mode) { + return float64_default_nan(status); + } + + if (mantissa) { + return make_float64( + (((uint64_t) a.sign) << 63) + | UINT64_C(0x7FF0000000000000) + | (a.high >> 12)); + } else { + return float64_default_nan(status); + } +} + +/*---------------------------------------------------------------------------- +| Takes two double-precision floating-point values `a' and `b', one of which +| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +static float64 propagateFloat64NaN(float64 a, float64 b, float_status *status) +{ + flag aIsLargerSignificand; + uint64_t av, bv; + FloatClass a_cls, b_cls; + + /* This is not complete, but is good enough for pickNaN. */ + a_cls = (!float64_is_any_nan(a) + ? float_class_normal + : float64_is_signaling_nan(a, status) + ? float_class_snan + : float_class_qnan); + b_cls = (!float64_is_any_nan(b) + ? float_class_normal + : float64_is_signaling_nan(b, status) + ? float_class_snan + : float_class_qnan); + + av = float64_val(a); + bv = float64_val(b); + + if (is_snan(a_cls) || is_snan(b_cls)) { + float_raise(float_flag_invalid, status); + } + + if (status->default_nan_mode) { + return float64_default_nan(status); + } + + if ((uint64_t)(av << 1) < (uint64_t)(bv << 1)) { + aIsLargerSignificand = 0; + } else if ((uint64_t)(bv << 1) < (uint64_t)(av << 1)) { + aIsLargerSignificand = 1; + } else { + aIsLargerSignificand = (av < bv) ? 1 : 0; + } + + if (pickNaN(a_cls, b_cls, aIsLargerSignificand)) { + if (is_snan(b_cls)) { + return float64_silence_nan(b, status); + } + return b; + } else { + if (is_snan(a_cls)) { + return float64_silence_nan(a, status); + } + return a; + } +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is a +| quiet NaN; otherwise returns 0. This slightly differs from the same +| function for other types as floatx80 has an explicit bit. +*----------------------------------------------------------------------------*/ + +int floatx80_is_quiet_nan(floatx80 a, float_status *status) +{ +#ifdef NO_SIGNALING_NANS + return floatx80_is_any_nan(a); +#else + if (snan_bit_is_one(status)) { + uint64_t aLow; + + aLow = a.low & ~0x4000000000000000ULL; + return ((a.high & 0x7FFF) == 0x7FFF) + && (aLow << 1) + && (a.low == aLow); + } else { + return ((a.high & 0x7FFF) == 0x7FFF) + && (UINT64_C(0x8000000000000000) <= ((uint64_t)(a.low << 1))); + } +#endif +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is a +| signaling NaN; otherwise returns 0. This slightly differs from the same +| function for other types as floatx80 has an explicit bit. +*----------------------------------------------------------------------------*/ + +int floatx80_is_signaling_nan(floatx80 a, float_status *status) +{ +#ifdef NO_SIGNALING_NANS + return 0; +#else + if (snan_bit_is_one(status)) { + return ((a.high & 0x7FFF) == 0x7FFF) + && ((a.low << 1) >= 0x8000000000000000ULL); + } else { + uint64_t aLow; + + aLow = a.low & ~UINT64_C(0x4000000000000000); + return ((a.high & 0x7FFF) == 0x7FFF) + && (uint64_t)(aLow << 1) + && (a.low == aLow); + } +#endif +} + +/*---------------------------------------------------------------------------- +| Returns a quiet NaN from a signalling NaN for the extended double-precision +| floating point value `a'. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_silence_nan(floatx80 a, float_status *status) +{ + /* None of the targets that have snan_bit_is_one use floatx80. */ + assert(!snan_bit_is_one(status)); + a.low |= UINT64_C(0xC000000000000000); + return a; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the extended double-precision floating- +| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the +| invalid exception is raised. +*----------------------------------------------------------------------------*/ + +static commonNaNT floatx80ToCommonNaN(floatx80 a, float_status *status) +{ + floatx80 dflt; + commonNaNT z; + + if (floatx80_is_signaling_nan(a, status)) { + float_raise(float_flag_invalid, status); + } + if (a.low >> 63) { + z.sign = a.high >> 15; + z.low = 0; + z.high = a.low << 1; + } else { + dflt = floatx80_default_nan(status); + z.sign = dflt.high >> 15; + z.low = 0; + z.high = dflt.low << 1; + } + return z; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the extended +| double-precision floating-point format. +*----------------------------------------------------------------------------*/ + +static floatx80 commonNaNToFloatx80(commonNaNT a, float_status *status) +{ + floatx80 z; + + if (status->default_nan_mode) { + return floatx80_default_nan(status); + } + + if (a.high >> 1) { + z.low = UINT64_C(0x8000000000000000) | a.high >> 1; + z.high = (((uint16_t)a.sign) << 15) | 0x7FFF; + } else { + z = floatx80_default_nan(status); + } + return z; +} + +/*---------------------------------------------------------------------------- +| Takes two extended double-precision floating-point values `a' and `b', one +| of which is a NaN, and returns the appropriate NaN result. If either `a' or +| `b' is a signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status) +{ + flag aIsLargerSignificand; + FloatClass a_cls, b_cls; + + /* This is not complete, but is good enough for pickNaN. */ + a_cls = (!floatx80_is_any_nan(a) + ? float_class_normal + : floatx80_is_signaling_nan(a, status) + ? float_class_snan + : float_class_qnan); + b_cls = (!floatx80_is_any_nan(b) + ? float_class_normal + : floatx80_is_signaling_nan(b, status) + ? float_class_snan + : float_class_qnan); + + if (is_snan(a_cls) || is_snan(b_cls)) { + float_raise(float_flag_invalid, status); + } + + if (status->default_nan_mode) { + return floatx80_default_nan(status); + } + + if (a.low < b.low) { + aIsLargerSignificand = 0; + } else if (b.low < a.low) { + aIsLargerSignificand = 1; + } else { + aIsLargerSignificand = (a.high < b.high) ? 1 : 0; + } + + if (pickNaN(a_cls, b_cls, aIsLargerSignificand)) { + if (is_snan(b_cls)) { + return floatx80_silence_nan(b, status); + } + return b; + } else { + if (is_snan(a_cls)) { + return floatx80_silence_nan(a, status); + } + return a; + } +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is a quiet +| NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +int float128_is_quiet_nan(float128 a, float_status *status) +{ +#ifdef NO_SIGNALING_NANS + return float128_is_any_nan(a); +#else + if (snan_bit_is_one(status)) { + return (((a.high >> 47) & 0xFFFF) == 0xFFFE) + && (a.low || (a.high & 0x00007FFFFFFFFFFFULL)); + } else { + return ((a.high << 1) >= 0xFFFF000000000000ULL) + && (a.low || (a.high & 0x0000FFFFFFFFFFFFULL)); + } +#endif +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is a +| signaling NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +int float128_is_signaling_nan(float128 a, float_status *status) +{ +#ifdef NO_SIGNALING_NANS + return 0; +#else + if (snan_bit_is_one(status)) { + return ((a.high << 1) >= 0xFFFF000000000000ULL) + && (a.low || (a.high & 0x0000FFFFFFFFFFFFULL)); + } else { + return (((a.high >> 47) & 0xFFFF) == 0xFFFE) + && (a.low || (a.high & UINT64_C(0x00007FFFFFFFFFFF))); + } +#endif +} + +/*---------------------------------------------------------------------------- +| Returns a quiet NaN from a signalling NaN for the quadruple-precision +| floating point value `a'. +*----------------------------------------------------------------------------*/ + +float128 float128_silence_nan(float128 a, float_status *status) +{ +#ifdef NO_SIGNALING_NANS + g_assert_not_reached(); +#else + if (snan_bit_is_one(status)) { + return float128_default_nan(status); + } else { + a.high |= UINT64_C(0x0000800000000000); + return a; + } +#endif +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the quadruple-precision floating-point NaN +| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ + +static commonNaNT float128ToCommonNaN(float128 a, float_status *status) +{ + commonNaNT z; + + if (float128_is_signaling_nan(a, status)) { + float_raise(float_flag_invalid, status); + } + z.sign = a.high >> 63; + shortShift128Left(a.high, a.low, 16, &z.high, &z.low); + return z; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the quadruple- +| precision floating-point format. +*----------------------------------------------------------------------------*/ + +static float128 commonNaNToFloat128(commonNaNT a, float_status *status) +{ + float128 z; + + if (status->default_nan_mode) { + return float128_default_nan(status); + } + + shift128Right(a.high, a.low, 16, &z.high, &z.low); + z.high |= (((uint64_t)a.sign) << 63) | UINT64_C(0x7FFF000000000000); + return z; +} + +/*---------------------------------------------------------------------------- +| Takes two quadruple-precision floating-point values `a' and `b', one of +| which is a NaN, and returns the appropriate NaN result. If either `a' or +| `b' is a signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +static float128 propagateFloat128NaN(float128 a, float128 b, + float_status *status) +{ + flag aIsLargerSignificand; + FloatClass a_cls, b_cls; + + /* This is not complete, but is good enough for pickNaN. */ + a_cls = (!float128_is_any_nan(a) + ? float_class_normal + : float128_is_signaling_nan(a, status) + ? float_class_snan + : float_class_qnan); + b_cls = (!float128_is_any_nan(b) + ? float_class_normal + : float128_is_signaling_nan(b, status) + ? float_class_snan + : float_class_qnan); + + if (is_snan(a_cls) || is_snan(b_cls)) { + float_raise(float_flag_invalid, status); + } + + if (status->default_nan_mode) { + return float128_default_nan(status); + } + + if (lt128(a.high << 1, a.low, b.high << 1, b.low)) { + aIsLargerSignificand = 0; + } else if (lt128(b.high << 1, b.low, a.high << 1, a.low)) { + aIsLargerSignificand = 1; + } else { + aIsLargerSignificand = (a.high < b.high) ? 1 : 0; + } + + if (pickNaN(a_cls, b_cls, aIsLargerSignificand)) { + if (is_snan(b_cls)) { + return float128_silence_nan(b, status); + } + return b; + } else { + if (is_snan(a_cls)) { + return float128_silence_nan(a, status); + } + return a; + } +} diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 7ef0638..0638c9f 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -634,7 +634,7 @@ static inline float64 float64_pack_raw(FloatParts p) | are propagated from function inputs to output. These details are target- | specific. *----------------------------------------------------------------------------*/ -#include "softfloat-specialize.h" +#include "softfloat-specialize.inc.c" /* Canonicalize EXP and FRAC, setting CLS. */ static FloatParts sf_canonicalize(FloatParts part, const FloatFmt *parm, -- cgit v1.1 From 502700d0674919309a19bfd016ea0680c6b7747d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 8 Aug 2019 17:27:31 +0100 Subject: target/mips: rationalise softfloat includes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We should avoid including the whole of softfloat headers in cpu.h and explicitly include it only where we will be calling softfloat functions. We can use the -types.h in cpu.h for the few bits that are global. We also move the restore_snan_bit_mode into internal.h and include -helpers.h there. Signed-off-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Aleksandar Markovic --- linux-user/mips/cpu_loop.c | 1 + target/mips/cpu.h | 8 +------- target/mips/internal.h | 7 +++++++ target/mips/msa_helper.c | 1 + target/mips/op_helper.c | 1 + 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c index 0ba894f..39915b3 100644 --- a/linux-user/mips/cpu_loop.c +++ b/linux-user/mips/cpu_loop.c @@ -22,6 +22,7 @@ #include "qemu.h" #include "cpu_loop-common.h" #include "elf.h" +#include "internal.h" # ifdef TARGET_ABI_MIPSO32 # define MIPS_SYS(name, args) args, diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 21c0615..d235117 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -5,7 +5,7 @@ #include "cpu-qom.h" #include "exec/cpu-defs.h" -#include "fpu/softfloat.h" +#include "fpu/softfloat-types.h" #include "mips-defs.h" #define TCG_GUEST_DEFAULT_MO (0) @@ -1195,12 +1195,6 @@ void itc_reconfigure(struct MIPSITUState *tag); /* helper.c */ target_ulong exception_resume_pc(CPUMIPSState *env); -static inline void restore_snan_bit_mode(CPUMIPSState *env) -{ - set_snan_bit_is_one((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) == 0, - &env->active_fpu.fp_status); -} - static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc, target_ulong *cs_base, uint32_t *flags) { diff --git a/target/mips/internal.h b/target/mips/internal.h index d5aa549..ae29b57 100644 --- a/target/mips/internal.h +++ b/target/mips/internal.h @@ -7,6 +7,7 @@ #ifndef MIPS_INTERNAL_H #define MIPS_INTERNAL_H +#include "fpu/softfloat-helpers.h" /* MMU types, the first four entries have the same layout as the CP0C0_MT field. */ @@ -226,6 +227,12 @@ static inline void restore_flush_mode(CPUMIPSState *env) &env->active_fpu.fp_status); } +static inline void restore_snan_bit_mode(CPUMIPSState *env) +{ + set_snan_bit_is_one((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) == 0, + &env->active_fpu.fp_status); +} + static inline void restore_fp_status(CPUMIPSState *env) { restore_rounding_mode(env); diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c index a5a8657..f24061e 100644 --- a/target/mips/msa_helper.c +++ b/target/mips/msa_helper.c @@ -22,6 +22,7 @@ #include "internal.h" #include "exec/exec-all.h" #include "exec/helper-proto.h" +#include "fpu/softfloat.h" /* Data format min and max values */ #define DF_BITS(df) (1 << ((df) + 3)) diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c index 9e2e02f..f88a3ab 100644 --- a/target/mips/op_helper.c +++ b/target/mips/op_helper.c @@ -25,6 +25,7 @@ #include "exec/exec-all.h" #include "exec/cpu_ldst.h" #include "sysemu/kvm.h" +#include "fpu/softfloat.h" /*****************************************************************************/ /* Exceptions processing helpers */ -- cgit v1.1 From 135b03cb9defbd080b8834b30e3d45bed00c6137 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 8 Aug 2019 17:29:41 +0100 Subject: target/riscv: rationalise softfloat includes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We should avoid including the whole of softfloat headers in cpu.h and explicitly include it only where we will be calling softfloat functions. We can use the -types.h and -helpers.h in cpu.h for the few bits that are global. Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Reviewed-by: Philippe Mathieu-Daudé Acked-by: Palmer Dabbelt --- target/riscv/cpu.c | 1 + target/riscv/cpu.h | 2 +- target/riscv/fpu_helper.c | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index f8d07bd..6d52f97 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -27,6 +27,7 @@ #include "qemu/error-report.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" +#include "fpu/softfloat-helpers.h" /* RISC-V CPU definitions */ diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 0adb307..240b31e 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -22,7 +22,7 @@ #include "qom/cpu.h" #include "exec/cpu-defs.h" -#include "fpu/softfloat.h" +#include "fpu/softfloat-types.h" #define TCG_GUEST_DEFAULT_MO 0 diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c index b4f818a..0b79562 100644 --- a/target/riscv/fpu_helper.c +++ b/target/riscv/fpu_helper.c @@ -21,6 +21,7 @@ #include "qemu/host-utils.h" #include "exec/exec-all.h" #include "exec/helper-proto.h" +#include "fpu/softfloat.h" target_ulong riscv_cpu_get_fflags(CPURISCVState *env) { -- cgit v1.1 From 5f8ab0004e878a6cd0f50fa8659df4a4f853eea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 8 Aug 2019 17:30:35 +0100 Subject: targets (various): use softfloat-helpers.h where we can MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generally the cpu and non-FP helper files just want to manipulate the softfloat flags. For this they can just use the -helpers.h include which brings in a minimal number of inline helpers. Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson Reviewed-by: David Hildenbrand Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé --- target/alpha/helper.c | 2 +- target/microblaze/cpu.c | 2 +- target/s390x/cpu.c | 2 +- target/sh4/cpu.c | 3 +-- target/tricore/helper.c | 2 +- target/unicore32/cpu.c | 1 - 6 files changed, 5 insertions(+), 7 deletions(-) diff --git a/target/alpha/helper.c b/target/alpha/helper.c index 93b8e78..c699834 100644 --- a/target/alpha/helper.c +++ b/target/alpha/helper.c @@ -21,7 +21,7 @@ #include "cpu.h" #include "exec/exec-all.h" -#include "fpu/softfloat.h" +#include "fpu/softfloat-types.h" #include "exec/helper-proto.h" #include "qemu/qemu-print.h" diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c index 0bec54b..9cfd744 100644 --- a/target/microblaze/cpu.c +++ b/target/microblaze/cpu.c @@ -28,7 +28,7 @@ #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "exec/exec-all.h" -#include "fpu/softfloat.h" +#include "fpu/softfloat-helpers.h" static const struct { const char *name; diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c index 9466cd8..3abe7e8 100644 --- a/target/s390x/cpu.c +++ b/target/s390x/cpu.c @@ -42,7 +42,7 @@ #include "sysemu/sysemu.h" #include "sysemu/tcg.h" #endif -#include "fpu/softfloat.h" +#include "fpu/softfloat-helpers.h" #define CR0_RESET 0xE0UL #define CR14_RESET 0xC2000000UL; diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c index 816d6d7..d0a7707 100644 --- a/target/sh4/cpu.c +++ b/target/sh4/cpu.c @@ -25,8 +25,7 @@ #include "cpu.h" #include "migration/vmstate.h" #include "exec/exec-all.h" -#include "fpu/softfloat.h" - +#include "fpu/softfloat-helpers.h" static void superh_cpu_set_pc(CPUState *cs, vaddr value) { diff --git a/target/tricore/helper.c b/target/tricore/helper.c index a680336..d5db7b2 100644 --- a/target/tricore/helper.c +++ b/target/tricore/helper.c @@ -19,7 +19,7 @@ #include "cpu.h" #include "exec/exec-all.h" -#include "fpu/softfloat.h" +#include "fpu/softfloat-helpers.h" #include "qemu/qemu-print.h" enum { diff --git a/target/unicore32/cpu.c b/target/unicore32/cpu.c index 802e2f1..b27fb96 100644 --- a/target/unicore32/cpu.c +++ b/target/unicore32/cpu.c @@ -17,7 +17,6 @@ #include "cpu.h" #include "migration/vmstate.h" #include "exec/exec-all.h" -#include "fpu/softfloat.h" static void uc32_cpu_set_pc(CPUState *cs, vaddr value) { -- cgit v1.1