This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PR target/27681: Missing DImode float conversions on MIPS


You may remember a while ago we discussed and fixed a problem in which
libgcc was missing some functions on 64-bit MIPS targets:

    http://gcc.gnu.org/ml/gcc-patches/2006-05/msg00639.html

To recap, adding TImode functions for MIPS had caused some DImode
functions to be removed.

I've finally backported the patches to 4.1.  They fix PR 27681, which
is a regression from 4.0, and a major bug if you care about 64-bit MIPS
targets.  Hopefully the patches have been on trunk long enough without
problems for them to be "safe enough".

Tested on mipsisa64-elf and mips64-linux-gnu.  Also boostrapped
& regression-tested on x86_64-linux-gnu.  OK to install?

Richard


	PR target/27681

	Backport from mainline:

	2006-05-23  Richard Sandiford  <richard@codesourcery.com>

	* libgcc2.c (LIBGCC2_MAX_UNITS_PER_WORD): New macro.
	(LIBGCC2_UNITS_PER_WORD): Use LIBGCC2_MAX_UNITS_PER_WORD rather than
	MIN_UNITS_PER_WORD to set the default.  Also use it in the guard.

	2006-05-22  Richard Sandiford  <richard@codesourcery.com>

	* mklibgcc.in (lib2funcs): Remove _floatdidf from initial assignment.

	2006-05-19  Richard Sandiford  <richard@codesourcery.com>

	* libgcc2.c (MIN_UNITS_PER_WORD): Move default definition from
	libgcc2.h.
	(LIBGCC2_UNITS_PER_WORD): Provide default definition, using old
	MIN_UNITS_PER_WORD logic from libgcc2.h.  Do nothing if
	LIBGCC2_UNITS_PER_WORD > MIN_UNITS_PER_WORD.
	* libgcc2.h (MIN_UNITS_PER_WORD): Remove definition from here.
	Use LIBGCC2_UNITS_PER_WORD rather than MIN_UNITS_PER_WORD to
	determine the size of Wtype, etc.
	* mklibgcc.in (LIB2_SIDITI_CONV_FUNCS): New argument.
	(swfloatfuncs): New variable.
	(dwfloatfuncs): Likewise.
	(lib2funcs): Remove floating-point conversion functions from
	initial assignment.  Use LIB2_SIDITI_CONV_FUNCS to determine
	the set of conversion routines needed.  Allow entries to specify
	an object name, filename and word size.  Update users accordingly.
	* Makefile.in (libgcc.mk): Pass LIB2_SIDITI_CONV_FUNCS.
	* config/mips/t-mips (LIB2_SIDITI_CONV_FUNCS): Define.

	Revert:

	2006-02-08  Roger Sayle  <roger@eyesopen.com>

	PR target/22209
	* 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: gcc/libgcc2.c
===================================================================
--- gcc/libgcc2.c	(revision 113971)
+++ gcc/libgcc2.c	(working copy)
@@ -40,6 +40,23 @@ #define ATTRIBUTE_HIDDEN  __attribute__ 
 #define ATTRIBUTE_HIDDEN
 #endif
 
+#ifndef MIN_UNITS_PER_WORD
+#define MIN_UNITS_PER_WORD UNITS_PER_WORD
+#endif
+
+#ifndef LIBGCC2_UNITS_PER_WORD
+# if MIN_UNITS_PER_WORD > 4
+#  define LIBGCC2_UNITS_PER_WORD 8
+# elif (MIN_UNITS_PER_WORD > 2 \
+        || (MIN_UNITS_PER_WORD > 1 && LONG_LONG_TYPE_SIZE > 32))
+#  define LIBGCC2_UNITS_PER_WORD 4
+# else
+#  define LIBGCC2_UNITS_PER_WORD MIN_UNITS_PER_WORD
+# endif
+#endif
+
+#if LIBGCC2_UNITS_PER_WORD <= MIN_UNITS_PER_WORD
+
 #include "libgcc2.h"
 
 #ifdef DECLARE_LIBRARY_RENAMES
@@ -2010,3 +2027,4 @@ func_ptr __DTOR_LIST__[2] = {0, 0};
 #endif
 #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
 #endif /* L_ctors */
+#endif /* LIBGCC2_UNITS_PER_WORD <= MIN_UNITS_PER_WORD */
Index: gcc/libgcc2.h
===================================================================
--- gcc/libgcc2.h	(revision 113971)
+++ gcc/libgcc2.h	(working copy)
@@ -79,10 +79,6 @@ #define LIBGCC2_HAS_TF_MODE \
   (BITS_PER_UNIT == 8 && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
 #endif
 
-#ifndef MIN_UNITS_PER_WORD
-#define MIN_UNITS_PER_WORD UNITS_PER_WORD
-#endif
-
 /* In the first part of this file, we are interfacing to calls generated
    by the compiler itself.  These calls pass values into these routines
    which have very specific modes (rather than very specific types), and
@@ -155,7 +151,7 @@ #define double bogus_type
    turns out that no platform would define COMPAT_DIMODE_TRAPPING_ARITHMETIC
    if it existed.  */
 
-#if MIN_UNITS_PER_WORD > 4
+#if LIBGCC2_UNITS_PER_WORD == 8
 #define W_TYPE_SIZE (8 * BITS_PER_UNIT)
 #define Wtype	DItype
 #define UWtype	UDItype
@@ -166,8 +162,7 @@ #define UDWtype	UTItype
 #define __NW(a,b)	__ ## a ## di ## b
 #define __NDW(a,b)	__ ## a ## ti ## b
 #define COMPAT_SIMODE_TRAPPING_ARITHMETIC
-#elif MIN_UNITS_PER_WORD > 2 \
-      || (MIN_UNITS_PER_WORD > 1 && LONG_LONG_TYPE_SIZE > 32)
+#elif LIBGCC2_UNITS_PER_WORD == 4
 #define W_TYPE_SIZE (4 * BITS_PER_UNIT)
 #define Wtype	SItype
 #define UWtype	USItype
@@ -177,7 +172,7 @@ #define DWtype	DItype
 #define UDWtype	UDItype
 #define __NW(a,b)	__ ## a ## si ## b
 #define __NDW(a,b)	__ ## a ## di ## b
-#elif MIN_UNITS_PER_WORD > 1
+#elif LIBGCC2_UNITS_PER_WORD == 2
 #define W_TYPE_SIZE (2 * BITS_PER_UNIT)
 #define Wtype	HItype
 #define UWtype	UHItype
Index: gcc/mklibgcc.in
===================================================================
--- gcc/mklibgcc.in	(revision 113971)
+++ gcc/mklibgcc.in	(working copy)
@@ -24,6 +24,7 @@
 # FPBIT
 # FPBIT_FUNCS
 # LIB2_DIVMOD_FUNCS
+# LIB2_SIDITI_CONV_FUNCS
 # DPBIT
 # DPBIT_FUNCS
 # TPBIT
@@ -54,10 +55,27 @@ echo 'dirs = libgcc'
 echo
 
 # Library members defined in libgcc2.c.
+
+# The floating-point conversion routines that involve a single-word integer.
+# XX stands for the integer mode.
+swfloatfuncs=
+for mode in sf df xf; do
+  swfloatfuncs="$swfloatfuncs _fixuns${mode}XX"
+done
+
+# Likewise double-word routines.
+dwfloatfuncs=
+for mode in sf df xf tf; do
+  dwfloatfuncs="$dwfloatfuncs _fix${mode}XX _fixuns${mode}XX"
+  dwfloatfuncs="$dwfloatfuncs _floatXX${mode}"
+done
+
+# Entries of the form <objfile>:<func>:<wordsize> indicate that libgcc2.c
+# should be compiled with L<func> defined and with LIBGCC2_UNITS_PER_WORD
+# set to <wordsize>.  <objfile> is the name of the associated object file
+
 lib2funcs='_muldi3 _negdi2 _lshrdi3 _ashldi3 _ashrdi3
-	_cmpdi2 _ucmpdi2 _floatdidf _floatdisf _fixunsdfsi _fixunssfsi
-	_fixunsdfdi _fixdfdi _fixunssfdi _fixsfdi _fixxfdi _fixunsxfdi
-	_floatdixf _fixunsxfsi _fixtfdi _fixunstfdi _floatditf _clear_cache
+	_cmpdi2 _ucmpdi2 _clear_cache
 	_enable_execute_stack _trampoline __main _absvsi2 _absvdi2 _addvsi3
 	_addvdi3 _subvsi3 _subvdi3 _mulvsi3 _mulvdi3 _negvsi2 _negvdi2 _ctors
 	_ffssi2 _ffsdi2 _clz _clzsi2 _clzdi2 _ctzsi2 _ctzdi2 _popcount_tab
@@ -65,6 +83,21 @@ lib2funcs='_muldi3 _negdi2 _lshrdi3 _ash
 	_powixf2 _powitf2 _mulsc3 _muldc3 _mulxc3 _multc3 _divsc3 _divdc3
 	_divxc3 _divtc3'
 
+if [ "$LIB2_SIDITI_CONV_FUNCS" ]; then
+  for func in $swfloatfuncs; do
+    sifunc=`echo $func | sed -e 's/XX/si/'`
+    lib2funcs="$lib2funcs $sifunc:$sifunc:4"
+  done
+  for func in $dwfloatfuncs; do
+    difunc=`echo $func | sed -e 's/XX/di/'`
+    tifunc=`echo $func | sed -e 's/XX/ti/'`
+    lib2funcs="$lib2funcs $difunc:$difunc:4 $tifunc:$difunc:8"
+  done
+else
+  lib2funcs="$lib2funcs `echo $swfloatfuncs | sed -e 's/XX/si/g'`"
+  lib2funcs="$lib2funcs `echo $dwfloatfuncs | sed -e 's/XX/di/g'`"
+fi
+
 # Disable SHLIB_LINK if shared libgcc not enabled.
 if [ "@enable_shared@" = "no" ]; then
   SHLIB_LINK=""
@@ -145,8 +178,8 @@ fi
 # Remove any objects from lib2funcs and LIB2_DIVMOD_FUNCS that are
 # defined as optimized assembly code in LIB1ASMFUNCS.
 for name in $LIB1ASMFUNCS; do
-  lib2funcs=`echo $lib2funcs | sed -e 's/^'$name' //' \
-				   -e 's/ '$name' / /' \
+  lib2funcs=`echo $lib2funcs | sed -e 's/^'$name'[ :]//' \
+				   -e 's/ '$name'[ :]/ /' \
 				   -e 's/ '$name'$//'`
   LIB2_DIVMOD_FUNCS=`echo $LIB2_DIVMOD_FUNCS | sed -e 's/^'$name' //' \
 				                   -e 's/ '$name' / /' \
@@ -248,16 +281,25 @@ for ml in $MULTILIBS; do
   #
 
   for name in $lib2funcs; do
+    case $name in
+      *:*:*)
+	defines=`echo $name | sed -e 's/.*:\(.*\):\(.*\)/-DL\1 -DLIBGCC2_UNITS_PER_WORD=\2/'`
+	name=`echo $name | sed -e 's/\(.*\):.*:.*/\1/'`
+	;;
+      *)
+	defines="-DL$name"
+	;;
+    esac
     if [ "$libgcc_s_so" ]; then
       out="libgcc/${dir}/${name}${objext}"
       outS="libgcc/${dir}/${name}_s${objext}"
 
       echo $outS: $libgcc2_c_dep
-      echo "	$gcc_s_compile" $flags -DL$name -c '$(srcdir)/libgcc2.c' \
+      echo "	$gcc_s_compile" $flags $defines -c '$(srcdir)/libgcc2.c' \
 	-o $outS
 
       echo $out: $libgcc2_c_dep
-      echo "	$gcc_compile" $flags -DL$name '$(vis_hide)' \
+      echo "	$gcc_compile" $flags $defines '$(vis_hide)' \
         -c '$(srcdir)/libgcc2.c' -o $out
 
       echo $libgcc_a: $out
@@ -268,7 +310,7 @@ for ml in $MULTILIBS; do
     else
       out="libgcc/${dir}/${name}${objext}"
       echo ${out}: stmp-dirs '$(srcdir)/config/$(LIB1ASMSRC)'
-      echo "	$gcc_compile" $flags -DL$name -c '$(srcdir)/libgcc2.c' -o $out
+      echo "	$gcc_compile" $flags $defines -c '$(srcdir)/libgcc2.c' -o $out
       echo $libgcc_a: $out
     fi
   done
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 113971)
+++ gcc/Makefile.in	(working copy)
@@ -1332,6 +1332,7 @@ libgcc.mk: config.status Makefile mklibg
 	LIB2ADDEHSTATIC='$(LIB2ADDEHSTATIC)' \
 	LIB2ADDEHSHARED='$(LIB2ADDEHSHARED)' \
 	LIB2ADDEHDEP='$(LIB2ADDEHDEP)' \
+	LIB2_SIDITI_CONV_FUNCS='$(LIB2_SIDITI_CONV_FUNCS)' \
 	LIBUNWIND='$(LIBUNWIND)' \
 	LIBUNWINDDEP='$(LIBUNWINDDEP)' \
 	SHLIBUNWIND_LINK='$(SHLIBUNWIND_LINK)' \
Index: gcc/config/floatunditf.c
===================================================================
--- gcc/config/floatunditf.c	(revision 113971)
+++ gcc/config/floatunditf.c	(working copy)
@@ -1,25 +0,0 @@
-/* Public domain.  */
-#if __LDBL_MANT_DIG__ == 106 || __LDBL_MANT_DIG__ == 113
-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
-
Index: gcc/config/fixunstfdi.c
===================================================================
--- gcc/config/fixunstfdi.c	(revision 113971)
+++ gcc/config/fixunstfdi.c	(working copy)
@@ -1,35 +0,0 @@
-/* Public domain.  */
-#if __LDBL_MANT_DIG__ == 106 || __LDBL_MANT_DIG__ == 113
-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
Index: gcc/config/mips/t-iris6
===================================================================
--- gcc/config/mips/t-iris6	(revision 113971)
+++ gcc/config/mips/t-iris6	(working copy)
@@ -6,8 +6,6 @@ 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
-
 TPBIT = tp-bit.c
 
 tp-bit.c: $(srcdir)/config/fp-bit.c
Index: gcc/config/mips/t-linux64
===================================================================
--- gcc/config/mips/t-linux64	(revision 113971)
+++ gcc/config/mips/t-linux64	(working copy)
@@ -4,8 +4,6 @@ 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
-
 TPBIT = tp-bit.c
 
 tp-bit.c: $(srcdir)/config/fp-bit.c
Index: gcc/config/mips/t-mips
===================================================================
--- gcc/config/mips/t-mips	(revision 113971)
+++ gcc/config/mips/t-mips	(working copy)
@@ -19,3 +19,5 @@ 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
+
+LIB2_SIDITI_CONV_FUNCS=yes
Index: gcc/config/fixtfdi.c
===================================================================
--- gcc/config/fixtfdi.c	(revision 113971)
+++ gcc/config/fixtfdi.c	(working copy)
@@ -1,18 +0,0 @@
-/* Public domain.  */
-#if __LDBL_MANT_DIG__ == 106 || __LDBL_MANT_DIG__ == 113
-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
Index: gcc/config/floatditf.c
===================================================================
--- gcc/config/floatditf.c	(revision 113971)
+++ gcc/config/floatditf.c	(working copy)
@@ -1,25 +0,0 @@
-/* Public domain.  */
-#if __LDBL_MANT_DIG__ == 106 || __LDBL_MANT_DIG__ == 113
-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
-


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]