diff --git a/sys/arch/alpha/alpha/fp_complete.c b/sys/arch/alpha/alpha/fp_complete.c index a87130716714..c19ee22b53ee 100644 --- a/sys/arch/alpha/alpha/fp_complete.c +++ b/sys/arch/alpha/alpha/fp_complete.c @@ -1,4 +1,4 @@ -/* $NetBSD: fp_complete.c,v 1.21 2014/05/19 07:09:10 matt Exp $ */ +/* $NetBSD: fp_complete.c,v 1.22 2017/12/31 11:43:42 martin Exp $ */ /*- * Copyright (c) 2001 Ross Harvey @@ -35,7 +35,7 @@ #include /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: fp_complete.c,v 1.21 2014/05/19 07:09:10 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fp_complete.c,v 1.22 2017/12/31 11:43:42 martin Exp $"); #include "opt_compat_osf1.h" @@ -334,7 +334,7 @@ cvt_tq_gq(uint32_t inst_bits, struct lwp *l) inst.bits = inst_bits; stt(inst.float_detail.fb, &tfb, l); - tfc.i = float64_to_int64(tfb.i); + tfc.i = tfb.sign ? float64_to_int64(tfb.i) : float64_to_uint64(tfb.i); alpha_ldt(inst.float_detail.fc, &tfc); /* yes, ldt */ } diff --git a/sys/lib/libkern/softfloat.c b/sys/lib/libkern/softfloat.c index df107c707f43..5dce6eebffba 100644 --- a/sys/lib/libkern/softfloat.c +++ b/sys/lib/libkern/softfloat.c @@ -1,4 +1,4 @@ -/* $NetBSD: softfloat.c,v 1.5 2013/11/03 00:01:43 christos Exp $ */ +/* $NetBSD: softfloat.c,v 1.6 2017/12/31 11:43:42 martin Exp $ */ /* * This version hacked for use with gcc -msoft-float by bjh21. @@ -49,7 +49,7 @@ this code that are retained. #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: softfloat.c,v 1.5 2013/11/03 00:01:43 christos Exp $"); +__RCSID("$NetBSD: softfloat.c,v 1.6 2017/12/31 11:43:42 martin Exp $"); #endif /* LIBC_SCCS and not lint */ #ifdef SOFTFLOAT_FOR_GCC @@ -210,6 +210,38 @@ static int64 roundAndPackInt64( flag zSign, bits64 absZ0, bits64 absZ1 ) if ( absZ1 ) float_set_inexact(); return z; +} + +/* same as above, but for unsigned values */ +static uint64 roundAndPackUInt64( bits64 absZ0, bits64 absZ1 ) +{ + int8 roundingMode; + flag roundNearestEven, increment; + uint64 z; + + roundingMode = float_rounding_mode(); + roundNearestEven = ( roundingMode == float_round_nearest_even ); + increment = ( (sbits64) absZ1 < 0 ); + if ( ! roundNearestEven ) { + if ( roundingMode == float_round_to_zero ) { + increment = 0; + } + else { + increment = ( roundingMode == float_round_up ) && absZ1; + } + } + if ( increment ) { + ++absZ0; + if ( absZ0 == 0 ) { + float_raise( float_flag_invalid ); + return LIT64( 0x7FFFFFFFFFFFFFFF ); + } + absZ0 &= ~ ( ( (bits64) ( absZ1<<1 ) == 0 ) & roundNearestEven ); + } + z = absZ0; + if ( absZ1 ) float_set_inexact(); + return z; + } #endif @@ -2399,6 +2431,44 @@ int64 float64_to_int64( float64 a ) } +/* like above, but result is unsigned */ +uint64 float64_to_uint64( float64 a ) +{ + flag aSign; + int16 aExp, shiftCount; + bits64 aSig, aSigExtra; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + + if (aSign) { + return float64_to_int64(a); + } + + if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); + shiftCount = 0x433 - aExp; + if ( shiftCount <= 0 ) { + if ( 0x43E < aExp ) { + float_raise( float_flag_invalid ); + if ( ! aSign + || ( ( aExp == 0x7FF ) + && ( aSig != LIT64( 0x0010000000000000 ) ) ) + ) { + return LIT64( 0x7FFFFFFFFFFFFFFF ); + } + return (sbits64) LIT64( 0x8000000000000000 ); + } + aSigExtra = 0; + aSig <<= - shiftCount; + } + else { + shift64ExtraRightJamming( aSig, 0, shiftCount, &aSig, &aSigExtra ); + } + return roundAndPackUInt64( aSig, aSigExtra ); + +} + /* ------------------------------------------------------------------------------- Returns the result of converting the double-precision floating-point value diff --git a/sys/lib/libkern/softfloat.h b/sys/lib/libkern/softfloat.h index 94637c9a68a1..2de7d2e4e652 100644 --- a/sys/lib/libkern/softfloat.h +++ b/sys/lib/libkern/softfloat.h @@ -1,4 +1,4 @@ -/* $NetBSD: softfloat.h,v 1.4 2008/04/28 20:24:06 martin Exp $ */ +/* $NetBSD: softfloat.h,v 1.5 2017/12/31 11:43:42 martin Exp $ */ /* This is a derivative work. */ @@ -229,6 +229,7 @@ int float64_to_int32( float64 ); int float64_to_int32_round_to_zero( float64 ); #ifndef SOFTFLOAT_FOR_GCC /* __fix?fdi provided by libgcc2.c */ int64_t float64_to_int64( float64 ); +uint64_t float64_to_uint64( float64 ); int64_t float64_to_int64_round_to_zero( float64 ); #endif float32 float64_to_float32( float64 );