This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
MIPS64 soft-float: missing definition for __floatdidf and friends
- From: Adam Nemet <anemet at caviumnetworks dot com>
- To: roger at eyesopen dot com, gcc-patches at gcc dot gnu dot org
- Date: Tue, 9 May 2006 09:19:49 -0700
- Subject: MIPS64 soft-float: missing definition for __floatdidf and friends
It seems that after the fix from Roger in
http://gcc.gnu.org/ml/gcc-patches/2006-02/msg00409.html libgcc no
longer provides DF<->DI conversion functions.
Specifically, on mipsisa64-elf with -msoft-float, this testcase fails
to link with missing definitions for __fixdfdi, __fixunsdfsi (!),
__floatdidf and __floatundidf:
long long f (double d) { return d; }
double g (long long l) { return l; }
unsigned int ff (double d) { return d; }
double gg (unsigned long long l) { return l; }
main () {}
Before the patch there was implementation for each DF<->DI conversion
function in either libgcc2.c or fp-bit.c:
fix fixuns float floatun
SF<->SI fp-bit libgcc2 fp-bit fp-bit
SF<->DI libgcc2 libgcc2 libgcc2 libgcc2
SF<->TI
DF<->SI fp-bit libgcc2 fp-bit fp-bit
DF<->DI libgcc2 libgcc2 libgcc2 libgcc2
DF<->TI
TF<->SI
TF<->DI libgcc2 libgcc2 libgcc2 libgcc2
TF<->TI
After the patch, DWtype is TItype (since MIN_UNITS_PER_WORD is 8) so
the definitions for DI will be "moved up to" TImode:
fix fixuns float floatun
SF<->SI fp-bit fp-bit fp-bit
SF<->DI libgcc2
SF<->TI libgcc2 libgcc2 libgcc2 libgcc2
DF<->SI fp-bit fp-bit fp-bit
DF<->DI libgcc2
DF<->TI libgcc2 libgcc2 libgcc2 libgcc2
TF<->SI
TF<->DI config/ config/ config/ config/
TF<->TI libgcc2 libgcc2 libgcc2 libgcc2
As apparent from the table we are now missing most of the definitions
for DI mode conversions and some for SI mode.
The patch below follows the precedent set by Joseph and Roger and adds
definitions for the missing functions under config/. PPC64 solves the
same problem by defining similar wrappers in ppc64-fp.c.
With the patch, soft-float testresults are back to where they were
before Roger's patch (+162 passes) with one exception. The failure of
gcc.dg/ftrapv-2.c seems to unrelated to this isssue and soft-float
altogether because it fails with hard-float too. I also tested the
default multilib with no regressions. This is all on mipsisa64-elf.
OK to apply to mainline and to 4.1 later?
* config/fixsfdi.c: New file.
* config/fixdfdi.c: New file.
* config/fixunsdfsi.c: New file.
* config/fixunssfsi.c: New file.
* config/floatdisf.c: New file.
* config/floatdidf.c: New file.
* config/floatundisf.c: New file.
* config/floatundidf.c: New file.
* config/mips/t-mips (LIB2FUNCS_EXTRA): Set it.
* config/mips/t-linux64 (LIB2FUNCS_EXTRA): Append to value set in
t-mips.
* config/mips/t-iris6 (LIB2FUNCS_EXTRA): Same.
Index: config/floatundidf.c
===================================================================
--- config/floatundidf.c (revision 0)
+++ config/floatundidf.c (revision 0)
@@ -0,0 +1,16 @@
+/* Public domain. */
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef unsigned int UDItype __attribute__ ((mode (DI)));
+typedef float DFtype __attribute__ ((mode (DF)));
+
+DFtype __floatundidf (UDItype);
+
+DFtype
+__floatundidf (UDItype u)
+{
+ /* When the word size is small, we never get any rounding error. */
+ DFtype f = (USItype) (u >> (sizeof (USItype) * 8));
+ f *= 0x1p32f;
+ f += (USItype) u;
+ return f;
+}
Index: config/fixdfdi.c
===================================================================
--- config/fixdfdi.c (revision 0)
+++ config/fixdfdi.c (revision 0)
@@ -0,0 +1,28 @@
+/* Public domain. */
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef int DItype __attribute__ ((mode (DI)));
+typedef unsigned int UDItype __attribute__ ((mode (DI)));
+typedef float DFtype __attribute__ ((mode (DF)));
+
+DItype __fixdfdi (DFtype);
+
+/* This version is needed to prevent recursion; fixunsdfdi in libgcc
+ calls fixdfdi, which in turn calls calls fixunsdfdi. */
+
+static DItype
+local_fixunsdfdi (DFtype a)
+{
+ USItype hi, lo;
+
+ hi = a / (((UDItype) 1) << (sizeof (USItype) * 8));
+ lo = a - ((DFtype) hi) * (((UDItype) 1) << (sizeof (USItype) * 8));
+ return ((UDItype) hi << (sizeof (USItype) * 8)) | lo;
+}
+
+DItype
+__fixdfdi (DFtype a)
+{
+ if (a < 0)
+ return - local_fixunsdfdi (-a);
+ return local_fixunsdfdi (a);
+}
Index: config/fixunsdfsi.c
===================================================================
--- config/fixunsdfsi.c (revision 0)
+++ config/fixunsdfsi.c (revision 0)
@@ -0,0 +1,18 @@
+/* Public domain. */
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef int SItype __attribute__ ((mode (SI)));
+typedef float SFtype __attribute__ ((mode (SF)));
+typedef float DFtype __attribute__ ((mode (DF)));
+
+USItype __fixunsdfsi (DFtype);
+
+#define SItype_MIN \
+ (- ((SItype) (((USItype) 1 << ((sizeof (SItype) * 8) - 1)) - 1)) - 1)
+
+USItype
+__fixunsdfsi (DFtype a)
+{
+ if (a >= - (DFtype) SItype_MIN)
+ return (SItype) (a + SItype_MIN) - SItype_MIN;
+ return (SItype) a;
+}
Index: config/floatdisf.c
===================================================================
--- config/floatdisf.c (revision 0)
+++ config/floatdisf.c (revision 0)
@@ -0,0 +1,38 @@
+/* Public domain. */
+typedef int DItype __attribute__ ((mode (DI)));
+typedef unsigned int UDItype __attribute__ ((mode (DI)));
+typedef int SItype __attribute__ ((mode (SI)));
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef float SFtype __attribute__ ((mode (SF)));
+typedef float DFtype __attribute__ ((mode (DF)));
+
+SFtype __floatdisf (DItype);
+
+SFtype
+__floatdisf (DItype u)
+{
+ /* Protect against double-rounding error.
+ Represent any low-order bits, that might be truncated by a bit that
+ won't be lost. The bit can go in anywhere below the rounding position
+ of SFtype. A fixed mask and bit position handles all usual
+ configurations. */
+ if (53 < (sizeof (DItype) * 8)
+ && 53 > ((sizeof (DItype) * 8) - 53 + 24))
+ {
+ if (!(- ((DItype) 1 << 53) < u
+ && u < ((DItype) 1 << 53)))
+ {
+ if ((UDItype) u & (((UDItype) 1 << (sizeof (DItype) * 8 - 53)) - 1))
+ {
+ u &= ~ (((UDItype) 1 << (sizeof (DItype) * 8 - 53)) - 1);
+ u |= (UDItype) 1 << (sizeof (DItype) * 8 - 53);
+ }
+ }
+ }
+ /* Do the calculation in a wider type so that we don't lose any of
+ the precision of the high word while multiplying it. */
+ DFtype f = (SItype) (u >> (sizeof (SItype) * 8));
+ f *= 0x1p32f;
+ f += (USItype) u;
+ return (SFtype) f;
+}
Index: config/fixsfdi.c
===================================================================
--- config/fixsfdi.c (revision 0)
+++ config/fixsfdi.c (revision 0)
@@ -0,0 +1,30 @@
+/* Public domain. */
+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)));
+
+DItype __fixsfdi (SFtype);
+
+/* This version is needed to prevent recursion; fixunssfdi in libgcc
+ calls fixsfdi, which in turn calls calls fixunssfdi. */
+
+static DItype
+local_fixunssfdi (SFtype original_a)
+{
+ DFtype a = original_a;
+ USItype hi, lo;
+
+ hi = a / (((UDItype) 1) << (sizeof (USItype) * 8));
+ lo = a - ((DFtype) hi) * (((UDItype) 1) << (sizeof (USItype) * 8));
+ return ((UDItype) hi << (sizeof (USItype) * 8)) | lo;
+}
+
+DItype
+__fixsfdi (SFtype a)
+{
+ if (a < 0)
+ return - local_fixunssfdi (-a);
+ return local_fixunssfdi (a);
+}
Index: config/floatundisf.c
===================================================================
--- config/floatundisf.c (revision 0)
+++ config/floatundisf.c (revision 0)
@@ -0,0 +1,36 @@
+/* Public domain. */
+typedef int DItype __attribute__ ((mode (DI)));
+typedef unsigned int UDItype __attribute__ ((mode (DI)));
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef float SFtype __attribute__ ((mode (SF)));
+typedef float DFtype __attribute__ ((mode (DF)));
+
+SFtype __floatundisf (UDItype);
+
+SFtype
+__floatundisf (UDItype u)
+{
+ /* Protect against double-rounding error.
+ Represent any low-order bits, that might be truncated by a bit that
+ won't be lost. The bit can go in anywhere below the rounding position
+ of SFTYPE. A fixed mask and bit position handles all usual
+ configurations. */
+ if (53 < (sizeof (DItype) * 8)
+ && 53 > ((sizeof (DItype) * 8) - 53 + 24))
+ {
+ if (u >= ((UDItype) 1 << 53))
+ {
+ if ((UDItype) u & (((UDItype) 1 << (sizeof (DItype) * 8 - 53)) - 1))
+ {
+ u &= ~ (((UDItype) 1 << (sizeof (DItype) * 8 - 53)) - 1);
+ u |= (UDItype) 1 << (sizeof (DItype) * 8 - 53);
+ }
+ }
+ }
+ /* Do the calculation in a wider type so that we don't lose any of
+ the precision of the high word while multiplying it. */
+ DFtype f = (USItype) (u >> (sizeof (USItype) * 8));
+ f *= 0x1p32f;
+ f += (USItype) u;
+ return (SFtype) f;
+}
Index: config/mips/t-iris6
===================================================================
--- config/mips/t-iris6 (revision 113576)
+++ config/mips/t-iris6 (working copy)
@@ -6,7 +6,7 @@ MULTILIB_OSDIRNAMES=../lib32 ../lib ../l
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
-LIB2FUNCS_EXTRA = $(srcdir)/config/fixtfdi.c $(srcdir)/config/fixunstfdi.c $(srcdir)/config/floatditf.c $(srcdir)/config/floatunditf.c
+LIB2FUNCS_EXTRA += $(srcdir)/config/fixtfdi.c $(srcdir)/config/fixunstfdi.c $(srcdir)/config/floatditf.c $(srcdir)/config/floatunditf.c
TPBIT = tp-bit.c
Index: config/mips/t-linux64
===================================================================
--- config/mips/t-linux64 (revision 113576)
+++ config/mips/t-linux64 (working copy)
@@ -4,7 +4,7 @@ MULTILIB_OSDIRNAMES = ../lib32 ../lib ..
EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
-LIB2FUNCS_EXTRA = $(srcdir)/config/fixtfdi.c $(srcdir)/config/fixunstfdi.c $(srcdir)/config/floatditf.c $(srcdir)/config/floatunditf.c
+LIB2FUNCS_EXTRA += $(srcdir)/config/fixtfdi.c $(srcdir)/config/fixunstfdi.c $(srcdir)/config/floatditf.c $(srcdir)/config/floatunditf.c
TPBIT = tp-bit.c
Index: config/mips/t-mips
===================================================================
--- config/mips/t-mips (revision 113576)
+++ config/mips/t-mips (working copy)
@@ -19,3 +19,8 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
echo '#endif' >> fp-bit.c
echo '#define QUIET_NAN_NEGATED' >> fp-bit.c
cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+LIB2FUNCS_EXTRA = $(srcdir)/config/fixsfdi.c $(srcdir)/config/fixdfdi.c \
+ $(srcdir)/config/fixunssfsi.c $(srcdir)/config/fixunsdfsi.c \
+ $(srcdir)/config/floatdisf.c $(srcdir)/config/floatdidf.c \
+ $(srcdir)/config/floatundisf.c $(srcdir)/config/floatundidf.c
Index: config/floatdidf.c
===================================================================
--- config/floatdidf.c (revision 0)
+++ config/floatdidf.c (revision 0)
@@ -0,0 +1,17 @@
+/* Public domain. */
+typedef int SItype __attribute__ ((mode (SI)));
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef int DItype __attribute__ ((mode (DI)));
+typedef float DFtype __attribute__ ((mode (DF)));
+
+DFtype __floatdidf (DItype);
+
+DFtype
+__floatdidf (DItype u)
+{
+ /* When the word size is small, we never get any rounding error. */
+ DFtype f = (SItype) (u >> (sizeof (SItype) * 8));
+ f *= 0x1p32f;
+ f += (USItype) u;
+ return f;
+}
Index: config/fixunssfsi.c
===================================================================
--- config/fixunssfsi.c (revision 0)
+++ config/fixunssfsi.c (revision 0)
@@ -0,0 +1,17 @@
+/* Public domain. */
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef int SItype __attribute__ ((mode (SI)));
+typedef float SFtype __attribute__ ((mode (SF)));
+
+USItype __fixunssfsi (SFtype);
+
+#define SItype_MIN \
+ (- ((SItype) (((USItype) 1 << ((sizeof (SItype) * 8) - 1)) - 1)) - 1)
+
+USItype
+__fixunssfsi (SFtype a)
+{
+ if (a >= - (SFtype) SItype_MIN)
+ return (SItype) (a + SItype_MIN) - SItype_MIN;
+ return (SItype) a;
+}