summaryrefslogtreecommitdiff
path: root/sys/lib/libkern/softfloat.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/lib/libkern/softfloat.c')
-rw-r--r--sys/lib/libkern/softfloat.c87
1 files changed, 86 insertions, 1 deletions
diff --git a/sys/lib/libkern/softfloat.c b/sys/lib/libkern/softfloat.c
index 848407619ce..f8d75e0327c 100644
--- a/sys/lib/libkern/softfloat.c
+++ b/sys/lib/libkern/softfloat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: softfloat.c,v 1.2 2007/12/29 16:59:16 miod Exp $ */
+/* $OpenBSD: softfloat.c,v 1.3 2008/10/07 22:06:29 martynas Exp $ */
/* $NetBSD: softfloat.c,v 1.1 2001/04/26 03:10:47 ross Exp $ */
/*
@@ -213,6 +213,53 @@ static int64 roundAndPackInt64( flag zSign, bits64 absZ0, bits64 absZ1 )
return z;
}
+
+#ifdef __alpha__
+/*
+-------------------------------------------------------------------------------
+Takes the 128-bit fixed-point value formed by concatenating `absZ0' and
+`absZ1', with binary point between bits 63 and 64 (between the input words),
+and returns the properly rounded 64-bit integer corresponding to the input.
+If `zSign' is 1, the input is negated before being converted to an integer.
+Ordinarily, the fixed-point input is simply rounded to an integer, with
+the inexact exception raised if the input cannot be represented exactly as
+an integer.
+-------------------------------------------------------------------------------
+*/
+static int64 roundAndPackInt64NoOverflow( flag zSign, bits64 absZ0,
+ bits64 absZ1 )
+{
+ int8 roundingMode;
+ flag roundNearestEven, increment;
+ int64 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 {
+ if ( zSign ) {
+ increment = ( roundingMode == float_round_down ) && absZ1;
+ }
+ else {
+ increment = ( roundingMode == float_round_up ) && absZ1;
+ }
+ }
+ }
+ if ( increment ) {
+ ++absZ0;
+ absZ0 &= ~ ( ( (bits64) ( absZ1<<1 ) == 0 ) & roundNearestEven );
+ }
+ z = absZ0;
+ if ( zSign ) z = - z;
+ if ( absZ1 ) float_set_inexact();
+ return z;
+
+}
+#endif /* __alpha__ */
#endif
/*
@@ -2401,6 +2448,44 @@ int64 float64_to_int64( float64 a )
}
+#ifdef __alpha__
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the double-precision floating-point value
+`a' to the 64-bit two's complement integer format. The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic---which means in particular that the conversion is rounded
+according to the current rounding mode. If `a' is a NaN, the invalid
+exception is raised and zero is returned.
+-------------------------------------------------------------------------------
+*/
+int64 float64_to_int64_no_overflow( float64 a )
+{
+ flag aSign;
+ int16 aExp, shiftCount;
+ bits64 aSig, aSigExtra;
+
+ aSig = extractFloat64Frac( a );
+ aExp = extractFloat64Exp( a );
+ aSign = extractFloat64Sign( a );
+ if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
+ shiftCount = 0x433 - aExp;
+ if ( shiftCount <= 0 ) {
+ if ( 0x43E < aExp ) {
+ float_raise( float_flag_invalid );
+ return 0;
+ }
+ aSigExtra = 0;
+ aSig <<= - shiftCount;
+ }
+ else {
+ shift64ExtraRightJamming( aSig, 0, shiftCount, &aSig, &aSigExtra );
+ }
+ return roundAndPackInt64NoOverflow( aSign, aSig, aSigExtra );
+
+}
+#endif /* __alpha__ */
+
/*
-------------------------------------------------------------------------------
Returns the result of converting the double-precision floating-point value