summaryrefslogtreecommitdiff
path: root/lib/libc/softfloat/bits64/softfloat.c
diff options
context:
space:
mode:
authormartin <martin@NetBSD.org>2007-11-08 15:50:19 +0000
committermartin <martin@NetBSD.org>2007-11-08 15:50:19 +0000
commit5265977a9ee4b36c56e7250064c6d72b0d0f9100 (patch)
tree8702e90de7217c2982d3a1ef3dc2a31bef534fa4 /lib/libc/softfloat/bits64/softfloat.c
parent9651856b04ca018a5d3fd4786a9556d98a3e0f9b (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.c57
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