aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/wordsize-32/fixsfdi.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/wordsize-32/fixsfdi.c')
-rw-r--r--sysdeps/wordsize-32/fixsfdi.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/sysdeps/wordsize-32/fixsfdi.c b/sysdeps/wordsize-32/fixsfdi.c
new file mode 100644
index 0000000000..c0235d42a6
--- /dev/null
+++ b/sysdeps/wordsize-32/fixsfdi.c
@@ -0,0 +1,102 @@
+/* Convert float to 64-bit int.
+ Copyright (C) 1989, 1992-2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <endian.h>
+#include <stdlib.h>
+#include <bits/wordsize.h>
+#include <shlib-compat.h>
+
+#if __WORDSIZE != 32
+# error This is for 32-bit targets only
+#endif
+
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_6)
+
+typedef unsigned int UQItype __attribute__ ((mode (QI)));
+typedef int SItype __attribute__ ((mode (SI)));
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef int DItype __attribute__ ((mode (DI)));
+typedef unsigned int UDItype __attribute__ ((mode (DI)));
+typedef float SFtype __attribute__ ((mode (SF)));
+typedef float DFtype __attribute__ ((mode (DF)));
+#define Wtype SItype
+#define HWtype SItype
+#define DWtype DItype
+#define UWtype USItype
+#define UHWtype USItype
+#define UDWtype UDItype
+#define W_TYPE_SIZE 32
+
+#include <stdlib/longlong.h>
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+struct DWstruct { Wtype high, low;};
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+struct DWstruct { Wtype low, high;};
+#else
+#error Unhandled endianity
+#endif
+typedef union { struct DWstruct s; DWtype ll; } DWunion;
+
+
+#define WORD_SIZE __WORDSIZE
+#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
+
+
+DWtype
+___fixunssfDI (SFtype original_a)
+{
+ /* Convert the SFtype to a DFtype, because that is surely not going
+ to lose any bits. Some day someone else can write a faster version
+ that avoids converting to DFtype, and verify it really works right. */
+ DFtype a = original_a;
+ DFtype b;
+ UDWtype v;
+
+ if (a < 0)
+ return 0;
+
+ /* Compute high word of result, as a flonum. */
+ b = (a / HIGH_WORD_COEFF);
+ /* Convert that to fixed (but not to DWtype!),
+ and shift it into the high word. */
+ v = (UWtype) b;
+ v <<= WORD_SIZE;
+ /* Remove high part from the DFtype, leaving the low part as flonum. */
+ a -= (DFtype) v;
+ /* Convert that to fixed (but not to DWtype!) and add it in.
+ Sometimes A comes out negative. This is significant, since
+ A has more bits than a long int does. */
+ if (a < 0)
+ v -= (UWtype) (- a);
+ else
+ v += (UWtype) a;
+ return v;
+}
+symbol_version (___fixunssfDI, __fixunssfDI, GLIBC_2.0);
+
+
+DWtype
+___fixsfdi (SFtype a)
+{
+ if (a < 0)
+ return - __fixunssfDI (-a);
+ return __fixunssfDI (a);
+}
+symbol_version (___fixsfdi, __fixsfdi, GLIBC_2.0);