This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[MIPS] PR target/22209: Support TImode arithmetic on MIPS
- From: Roger Sayle <roger at eyesopen dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 5 Feb 2006 14:38:53 -0700 (MST)
- Subject: [MIPS] PR target/22209: Support TImode arithmetic on MIPS
The following patch resolves PR target/22209 but adding support for
TImode arithmetic operations on MIPS targets. On IRIX, this changes
the gfortran testsuite results from 1547 PASSes and 4849 FAILs into
11446 PASSes and 12 FAILs. The trick is to avoid defining
MIN_UNITS_PER_WORD when building libgcc, so that libgcc2.c creates
all the double word arithmetic, __multi3, __divti3, etc.. that
we need. Thanks to the s390 folks for a similar recent fix.
The tricky part is that this simple change then exposes us to
a PR middle-end/24998-like bug as we then fail to have symbols
for __floatunsdidf and friends. The solution is to follow jsm28's
lead, and generic functions to gcc/config that may be included
by backends that need them. This allows us to get rid of mips'
_tilib.c source file, and could be used to slim down rs6000's
ppc64-fp.c. Perhaps this'll all be cleaned up if/when libgcc
moves to the top-level.
The following patch has been tested on mips-sgi-irix6.5 with a
full "make bootstrap", all default languages, and regression
tested with a top-level "make -k check" with no new failures,
and a significant improvement of the gfortran results.
Ok for mainline? This is also a regression in 4.1, but I'd
hope that this could be tested on several MIPS targets before
we decide whether or not to backport to the pending release
branch.
2006-02-05 Roger Sayle <roger@eyesopen.com>
PR target/22209
* config/mips/mips.h (MIN_UNITS_PER_WORD): Don't define for libgcc.
* config/mips/_tilib.c: Remove.
* config/fixtfdi.c: New libgcc source file.
* config/fixunstfdi.c: New source file.
* config/floatditf.c: New source file.
* config/floatunditf.c: New souce file.
* config/mips/t-iris6 (LIB2FUNCS_EXTRA): Include the new source
files above instead of config/mips/_tilib.c.
* config/mips/t-linux64 (LIB2FUNCS_EXTRA): Likewise.
Index: t-iris6
===================================================================
*** t-iris6 (revision 110497)
--- t-iris6 (working copy)
*************** MULTILIB_OSDIRNAMES=../lib32 ../lib ../l
*** 6,12 ****
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
! LIB2FUNCS_EXTRA = $(srcdir)/config/mips/_tilib.c
TPBIT = tp-bit.c
--- 6,12 ----
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
TPBIT = tp-bit.c
Index: t-linux64
===================================================================
*** t-linux64 (revision 110497)
--- t-linux64 (working copy)
*************** MULTILIB_OSDIRNAMES = ../lib32 ../lib ..
*** 4,10 ****
EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
! LIB2FUNCS_EXTRA = $(srcdir)/config/mips/_tilib.c
TPBIT = tp-bit.c
--- 4,10 ----
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
TPBIT = tp-bit.c
Index: mips.h
===================================================================
*** mips.h (revision 110497)
--- mips.h (working copy)
*************** extern const struct mips_rtx_cost_data *
*** 975,981 ****
--- 975,983 ----
/* Width of a word, in units (bytes). */
#define UNITS_PER_WORD (TARGET_64BIT ? 8 : 4)
+ #ifndef IN_LIBGCC2
#define MIN_UNITS_PER_WORD 4
+ #endif
/* For MIPS, width of a floating point register. */
#define UNITS_PER_FPREG (TARGET_FLOAT64 ? 8 : 4)
/* Public domain. */
#if __LDBL_MANT_DIG__ == 106
typedef int DItype __attribute__ ((mode (DI)));
typedef float TFtype __attribute__ ((mode (TF)));
DItype __fixtfdi (TFtype);
DItype __fixunstfdi (TFtype);
DItype
__fixtfdi (TFtype x)
{
if (x < 0)
return - __fixunstfdi (-x);
return __fixunstfdi (x);
}
#endif
/* Public domain. */
#if __LDBL_MANT_DIG__ == 106
typedef int DItype __attribute__ ((mode (DI)));
typedef int SItype __attribute__ ((mode (SI)));
typedef unsigned int UDItype __attribute__ ((mode (DI)));
typedef unsigned int USItype __attribute__ ((mode (SI)));
typedef float TFtype __attribute__ ((mode (TF)));
DItype __fixunstfdi (TFtype);
DItype
__fixunstfdi (TFtype a)
{
if (a < 0)
return 0;
/* Compute high word of result, as a flonum. */
const TFtype b = (a / (((UDItype) 1) << (sizeof (SItype) * 8)));
/* Convert that to fixed (but not to DItype!),
and shift it into the high word. */
UDItype v = (USItype) b;
v <<= (sizeof (SItype) * 8);
/* Remove high part from the TFtype, leaving the low part as flonum. */
a -= (TFtype) v;
/* Convert that to fixed (but not to DItype!) 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 -= (USItype) (-a);
else
v += (USItype) a;
return v;
}
#endif
/* Public domain. */
#if __LDBL_MANT_DIG__ == 106
typedef int DItype __attribute__ ((mode (DI)));
typedef int SItype __attribute__ ((mode (SI)));
typedef unsigned int UDItype __attribute__ ((mode (DI)));
typedef unsigned int USItype __attribute__ ((mode (SI)));
typedef float DFtype __attribute__ ((mode (DF)));
typedef float TFtype __attribute__ ((mode (TF)));
TFtype __floatditf (UDItype);
TFtype
__floatditf (UDItype u)
{
DFtype dh, dl;
dh = (SItype) (u >> (sizeof (SItype) * 8));
dh *= 2.0 * (((UDItype) 1) << ((sizeof (SItype) * 8) - 1));
dl = (USItype) (u & ((((UDItype) 1) << (sizeof (SItype) * 8)) - 1));
return (TFtype) dh + (TFtype) dl;
}
#endif
/* Public domain. */
#if __LDBL_MANT_DIG__ == 106
typedef int DItype __attribute__ ((mode (DI)));
typedef int SItype __attribute__ ((mode (SI)));
typedef unsigned int UDItype __attribute__ ((mode (DI)));
typedef unsigned int USItype __attribute__ ((mode (SI)));
typedef float DFtype __attribute__ ((mode (DF)));
typedef float TFtype __attribute__ ((mode (TF)));
TFtype __floatunditf (UDItype);
TFtype
__floatunditf (UDItype u)
{
DFtype dh, dl;
dh = (USItype) (u >> (sizeof (SItype) * 8));
dh *= 2.0 * (((UDItype) 1) << ((sizeof (SItype) * 8) - 1));
dl = (USItype) (u & ((((UDItype) 1) << (sizeof (SItype) * 8)) - 1));
return (TFtype) dh + (TFtype) dl;
}
#endif
Roger
--