diff options
| author | martin <martin@NetBSD.org> | 2007-11-08 15:50:19 +0000 |
|---|---|---|
| committer | martin <martin@NetBSD.org> | 2007-11-08 15:50:19 +0000 |
| commit | 5265977a9ee4b36c56e7250064c6d72b0d0f9100 (patch) | |
| tree | 8702e90de7217c2982d3a1ef3dc2a31bef534fa4 /lib/libc/softfloat/bits64/softfloat.c | |
| parent | 9651856b04ca018a5d3fd4786a9556d98a3e0f9b (diff) | |
When converting long double values to integer types, explicitly use the
"round to zero" variants of the softfloat conversion functions.
Add a variant to convert long double to unsigned long - the "to long"
variant checked for overflows that do not apply to unsigned results.
This fixes the regress/lib/libc/convfp tests for sparc64.
Diffstat (limited to 'lib/libc/softfloat/bits64/softfloat.c')
| -rw-r--r-- | lib/libc/softfloat/bits64/softfloat.c | 57 |
1 files changed, 55 insertions, 2 deletions
diff --git a/lib/libc/softfloat/bits64/softfloat.c b/lib/libc/softfloat/bits64/softfloat.c index 6d1370c90f0..edf56b9f11e 100644 --- a/lib/libc/softfloat/bits64/softfloat.c +++ b/lib/libc/softfloat/bits64/softfloat.c @@ -1,4 +1,4 @@ -/* $NetBSD: softfloat.c,v 1.3 2006/05/11 16:38:44 mrg Exp $ */ +/* $NetBSD: softfloat.c,v 1.4 2007/11/08 15:50:24 martin Exp $ */ /* * This version hacked for use with gcc -msoft-float by bjh21. @@ -46,7 +46,7 @@ this code that are retained. #include <sys/cdefs.h> #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: softfloat.c,v 1.3 2006/05/11 16:38:44 mrg Exp $"); +__RCSID("$NetBSD: softfloat.c,v 1.4 2007/11/08 15:50:24 martin Exp $"); #endif /* LIBC_SCCS and not lint */ #ifdef SOFTFLOAT_FOR_GCC @@ -4441,6 +4441,59 @@ int64 float128_to_int64_round_to_zero( float128 a ) } /* + * just like above - but do not care for overflow of signed results + */ +uint64 float128_to_uint64_round_to_zero( float128 a ) +{ + flag aSign; + int32 aExp, shiftCount; + bits64 aSig0, aSig1; + uint64 z; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); + shiftCount = aExp - 0x402F; + if ( 0 < shiftCount ) { + if ( 0x403F <= aExp ) { + aSig0 &= LIT64( 0x0000FFFFFFFFFFFF ); + if ( ( a.high == LIT64( 0xC03E000000000000 ) ) + && ( aSig1 < LIT64( 0x0002000000000000 ) ) ) { + if ( aSig1 ) float_exception_flags |= float_flag_inexact; + } + else { + float_raise( float_flag_invalid ); + if ( ! aSign || ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) ) { + return LIT64( 0x7FFFFFFFFFFFFFFF ); + } + } + return (sbits64) LIT64( 0x8000000000000000 ); + } + z = ( aSig0<<shiftCount ) | ( aSig1>>( ( - shiftCount ) & 63 ) ); + if ( (bits64) ( aSig1<<shiftCount ) ) { + float_exception_flags |= float_flag_inexact; + } + } + else { + if ( aExp < 0x3FFF ) { + if ( aExp | aSig0 | aSig1 ) { + float_exception_flags |= float_flag_inexact; + } + return 0; + } + z = aSig0>>( - shiftCount ); + if (aSig1 || ( shiftCount && (bits64) ( aSig0<<( shiftCount & 63 ) ) ) ) { + float_exception_flags |= float_flag_inexact; + } + } + if ( aSign ) z = - z; + return z; + +} + +/* ------------------------------------------------------------------------------- Returns the result of converting the quadruple-precision floating-point value `a' to the single-precision floating-point format. The conversion |
