Blame SOURCES/gcc34-libgcc-additions.patch

6fdc0f
2007-01-05  Jakub Jelinek  <jakub@redhat.com>
6fdc0f
6fdc0f
	PR c/30360
6fdc0f
	* libgcc2.c (__divdc3): Compare c and d against 0.0 instead of
6fdc0f
	denom against 0.0.
6fdc0f
6fdc0f
2005-11-22  Joseph S. Myers  <joseph@codesourcery.com>
6fdc0f
6fdc0f
	* libgcc-std.ver (GCC_4.2.0): New version.
6fdc0f
	* libgcc2.c (__floatundixf, __floatunditf, __floatundidf,
6fdc0f
	__floatundisf): New functions.
6fdc0f
	* libgcc2.h (__floatundixf, __floatunditf, __floatundidf,
6fdc0f
	__floatundisf): Declare.
6fdc0f
	* mklibgcc.in (lib2funcs): Add _floatundidf, _floatundisf,
6fdc0f
	_floatundixf, and _floatunditf.
6fdc0f
6fdc0f
2005-03-30 Fariborz Jahanian <fjahanian@apple.com>
6fdc0f
6fdc0f
	* libgcc2.h (__powisf2, __powidf2, __powixf2, __powitf2): Change
6fdc0f
	2nd argument type to int.
6fdc0f
	* libgcc2.c: Change prototype of __powi* functions to use
6fdc0f
	int.
6fdc0f
6fdc0f
2005-02-11  Richard Henderson  <rth@redhat.com>
6fdc0f
6fdc0f
	* libgcc2.c (__divsc3, __divdc3, __divxc3, __divtc3,
6fdc0f
	__mulsc3, __muldc3, __mulxc3, __multc3): New.
6fdc0f
	* libgcc2.h: Declare them.
6fdc0f
 	* libgcc-std.ver: Export them.
6fdc0f
	* mklibgcc.in (lib2funcs): Build them.
6fdc0f
6fdc0f
2005-02-09  Richard Guenther  <rguenth@gcc.gnu.org>
6fdc0f
6fdc0f
	PR middle-end/19402
6fdc0f
	* libgcc2.h: Add prototypes for __builtin_powi[lf].
6fdc0f
	* libgcc2.c: Add __builtin_powi[lf] implementation.
6fdc0f
	* mklibgcc.in: Add __builtin_powi[lf] to lib2funcs.
6fdc0f
6fdc0f
--- gcc/libgcc-std.ver.jj	2007-03-02 09:27:16.000000000 +0100
6fdc0f
+++ gcc/libgcc-std.ver	2007-03-02 10:32:27.000000000 +0100
6fdc0f
@@ -235,7 +235,39 @@ GCC_3.4.4 {
6fdc0f
   __subvti3
6fdc0f
 }
6fdc0f
 
6fdc0f
-%inherit GCC_4.2.0 GCC_3.4.4
6fdc0f
+%inherit GCC_4.0.0 GCC_3.4.4
6fdc0f
+GCC_4.0.0 {
6fdc0f
+  # libgcc2 __builtin_powi helpers.
6fdc0f
+  __powisf2
6fdc0f
+  __powidf2
6fdc0f
+  __powixf2
6fdc0f
+  __powitf2
6fdc0f
+
6fdc0f
+  # c99 compliant complex arithmetic
6fdc0f
+  __divsc3
6fdc0f
+  __divdc3
6fdc0f
+  __divxc3
6fdc0f
+  __divtc3
6fdc0f
+  __mulsc3
6fdc0f
+  __muldc3
6fdc0f
+  __mulxc3
6fdc0f
+  __multc3
6fdc0f
+}
6fdc0f
+
6fdc0f
+%inherit GCC_4.2.0 GCC_4.0.0
6fdc0f
 GCC_4.2.0 {
6fdc0f
+  # unsigned-to-floating conversions
6fdc0f
+  __floatunsisf
6fdc0f
+  __floatunsidf
6fdc0f
+  __floatunsixf
6fdc0f
+  __floatunsitf
6fdc0f
+  __floatundidf
6fdc0f
+  __floatundisf
6fdc0f
+  __floatundixf
6fdc0f
+  __floatunditf
6fdc0f
+  __floatuntidf
6fdc0f
+  __floatuntisf
6fdc0f
+  __floatuntixf
6fdc0f
+  __floatuntitf
6fdc0f
   _Unwind_GetIPInfo
6fdc0f
 }
6fdc0f
--- gcc/libgcc2.h.jj	2006-10-05 00:37:01.000000000 +0200
6fdc0f
+++ gcc/libgcc2.h	2007-03-02 11:26:31.000000000 +0100
6fdc0f
@@ -88,12 +88,16 @@ typedef unsigned int UTItype	__attribute
6fdc0f
 
6fdc0f
 typedef 	float SFtype	__attribute__ ((mode (SF)));
6fdc0f
 typedef		float DFtype	__attribute__ ((mode (DF)));
6fdc0f
+typedef _Complex float SCtype;
6fdc0f
+typedef _Complex double DCtype;
6fdc0f
 
6fdc0f
 #if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
6fdc0f
 typedef		float XFtype	__attribute__ ((mode (XF)));
6fdc0f
+typedef _Complex long double XCtype;
6fdc0f
 #endif
6fdc0f
 #if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128
6fdc0f
 typedef		float TFtype	__attribute__ ((mode (TF)));
6fdc0f
+typedef _Complex long double TCtype;
6fdc0f
 #endif
6fdc0f
 
6fdc0f
 #else /* BITS_PER_UNIT != 8 */
6fdc0f
@@ -216,6 +220,10 @@ typedef int word_type __attribute__ ((mo
6fdc0f
 #define __floatditf	__NDW(float,tf)
6fdc0f
 #define __floatdidf	__NDW(float,df)
6fdc0f
 #define __floatdisf	__NDW(float,sf)
6fdc0f
+#define __floatundixf	__NDW(floatun,xf)
6fdc0f
+#define __floatunditf	__NDW(floatun,tf)
6fdc0f
+#define __floatundidf	__NDW(floatun,df)
6fdc0f
+#define __floatundisf	__NDW(floatun,sf)
6fdc0f
 #define __fixunsxfSI	__NW(fixunsxf,)
6fdc0f
 #define __fixunstfSI	__NW(fixunstf,)
6fdc0f
 #define __fixunsdfSI	__NW(fixunsdf,)
6fdc0f
@@ -293,27 +301,47 @@ extern SItype __negvsi2 (SItype);
6fdc0f
 #endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
6fdc0f
 
6fdc0f
 #if BITS_PER_UNIT == 8
6fdc0f
+#undef int
6fdc0f
 extern DWtype __fixdfdi (DFtype);
6fdc0f
 extern DWtype __fixsfdi (SFtype);
6fdc0f
 extern DFtype __floatdidf (DWtype);
6fdc0f
 extern SFtype __floatdisf (DWtype);
6fdc0f
+extern DFtype __floatundidf (UDWtype);
6fdc0f
+extern SFtype __floatundisf (UDWtype);
6fdc0f
 extern UWtype __fixunsdfSI (DFtype);
6fdc0f
 extern UWtype __fixunssfSI (SFtype);
6fdc0f
 extern DWtype __fixunsdfDI (DFtype);
6fdc0f
 extern DWtype __fixunssfDI (SFtype);
6fdc0f
+extern SFtype __powisf2 (SFtype, int);
6fdc0f
+extern DFtype __powidf2 (DFtype, int);
6fdc0f
+
6fdc0f
+extern SCtype __divsc3 (SFtype, SFtype, SFtype, SFtype);
6fdc0f
+extern SCtype __mulsc3 (SFtype, SFtype, SFtype, SFtype);
6fdc0f
+extern DCtype __divdc3 (DFtype, DFtype, DFtype, DFtype);
6fdc0f
+extern DCtype __muldc3 (DFtype, DFtype, DFtype, DFtype);
6fdc0f
 
6fdc0f
 #if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
6fdc0f
 extern DWtype __fixxfdi (XFtype);
6fdc0f
 extern DWtype __fixunsxfDI (XFtype);
6fdc0f
 extern XFtype __floatdixf (DWtype);
6fdc0f
+extern XFtype __floatundixf (UDWtype);
6fdc0f
 extern UWtype __fixunsxfSI (XFtype);
6fdc0f
+extern XFtype __powixf2 (XFtype, int);
6fdc0f
+extern XCtype __divxc3 (XFtype, XFtype, XFtype, XFtype);
6fdc0f
+extern XCtype __mulxc3 (XFtype, XFtype, XFtype, XFtype);
6fdc0f
 #endif
6fdc0f
 
6fdc0f
 #if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128
6fdc0f
 extern DWtype __fixunstfDI (TFtype);
6fdc0f
 extern DWtype __fixtfdi (TFtype);
6fdc0f
 extern TFtype __floatditf (DWtype);
6fdc0f
+extern TFtype __floatunditf (UDWtype);
6fdc0f
+extern TFtype __powitf2 (TFtype, int);
6fdc0f
+extern TCtype __divtc3 (TFtype, TFtype, TFtype, TFtype);
6fdc0f
+extern TCtype __multc3 (TFtype, TFtype, TFtype, TFtype);
6fdc0f
 #endif
6fdc0f
+
6fdc0f
+#define int bogus_type
6fdc0f
 #endif /* BITS_PER_UNIT == 8 */
6fdc0f
 
6fdc0f
 /* DWstructs are pairs of Wtype values in the order determined by
6fdc0f
--- gcc/mklibgcc.in.jj	2006-10-05 00:37:01.000000000 +0200
6fdc0f
+++ gcc/mklibgcc.in	2007-03-02 10:31:58.000000000 +0100
6fdc0f
@@ -58,7 +58,9 @@ lib2funcs='_muldi3 _negdi2 _lshrdi3 _ash
6fdc0f
 	_enable_execute_stack _trampoline __main _absvsi2 _absvdi2 _addvsi3
6fdc0f
 	_addvdi3 _subvsi3 _subvdi3 _mulvsi3 _mulvdi3 _negvsi2 _negvdi2 _ctors
6fdc0f
 	_ffssi2 _ffsdi2 _clz _clzsi2 _clzdi2 _ctzsi2 _ctzdi2 _popcount_tab
6fdc0f
-	_popcountsi2 _popcountdi2 _paritysi2 _paritydi2'
6fdc0f
+	_popcountsi2 _popcountdi2 _paritysi2 _paritydi2 _powisf2 _powidf2
6fdc0f
+	_powixf2 _powitf2 _mulsc3 _muldc3 _mulxc3 _multc3 _divsc3 _divdc3
6fdc0f
+	_divxc3 _divtc3 _floatundidf _floatundisf _floatundixf _floatunditf'
6fdc0f
 
6fdc0f
 # Disable SHLIB_LINK if shared libgcc not enabled.
6fdc0f
 if [ "@enable_shared@" = "no" ]; then
6fdc0f
--- gcc/libgcc2.c.jj	2006-10-05 00:37:01.000000000 +0200
6fdc0f
+++ gcc/libgcc2.c	2007-03-02 10:58:07.000000000 +0100
6fdc0f
@@ -1331,6 +1331,23 @@ __floatdixf (DWtype u)
6fdc0f
 }
6fdc0f
 #endif
6fdc0f
 
6fdc0f
+#if defined(L_floatundixf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
6fdc0f
+#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
6fdc0f
+#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
6fdc0f
+#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
6fdc0f
+
6fdc0f
+XFtype
6fdc0f
+__floatundixf (UDWtype u)
6fdc0f
+{
6fdc0f
+  XFtype d = (UWtype) (u >> WORD_SIZE);
6fdc0f
+  d *= HIGH_HALFWORD_COEFF;
6fdc0f
+  d *= HIGH_HALFWORD_COEFF;
6fdc0f
+  d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
6fdc0f
+
6fdc0f
+  return d;
6fdc0f
+}
6fdc0f
+#endif
6fdc0f
+
6fdc0f
 #if defined(L_floatditf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
6fdc0f
 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
6fdc0f
 #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
6fdc0f
@@ -1348,6 +1365,23 @@ __floatditf (DWtype u)
6fdc0f
 }
6fdc0f
 #endif
6fdc0f
 
6fdc0f
+#if defined(L_floatunditf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
6fdc0f
+#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
6fdc0f
+#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
6fdc0f
+#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
6fdc0f
+
6fdc0f
+TFtype
6fdc0f
+__floatunditf (UDWtype u)
6fdc0f
+{
6fdc0f
+  TFtype d = (UWtype) (u >> WORD_SIZE);
6fdc0f
+  d *= HIGH_HALFWORD_COEFF;
6fdc0f
+  d *= HIGH_HALFWORD_COEFF;
6fdc0f
+  d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
6fdc0f
+
6fdc0f
+  return d;
6fdc0f
+}
6fdc0f
+#endif
6fdc0f
+
6fdc0f
 #ifdef L_floatdidf
6fdc0f
 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
6fdc0f
 #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
6fdc0f
@@ -1365,6 +1399,23 @@ __floatdidf (DWtype u)
6fdc0f
 }
6fdc0f
 #endif
6fdc0f
 
6fdc0f
+#ifdef L_floatundidf
6fdc0f
+#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
6fdc0f
+#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
6fdc0f
+#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
6fdc0f
+
6fdc0f
+DFtype
6fdc0f
+__floatundidf (UDWtype u)
6fdc0f
+{
6fdc0f
+  DFtype d = (UWtype) (u >> WORD_SIZE);
6fdc0f
+  d *= HIGH_HALFWORD_COEFF;
6fdc0f
+  d *= HIGH_HALFWORD_COEFF;
6fdc0f
+  d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
6fdc0f
+
6fdc0f
+  return d;
6fdc0f
+}
6fdc0f
+#endif
6fdc0f
+
6fdc0f
 #ifdef L_floatdisf
6fdc0f
 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
6fdc0f
 #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
6fdc0f
@@ -1409,6 +1460,49 @@ __floatdisf (DWtype u)
6fdc0f
 }
6fdc0f
 #endif
6fdc0f
 
6fdc0f
+#ifdef L_floatundisf
6fdc0f
+#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
6fdc0f
+#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
6fdc0f
+#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
6fdc0f
+
6fdc0f
+#define DI_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
6fdc0f
+#define DF_SIZE DBL_MANT_DIG
6fdc0f
+#define SF_SIZE FLT_MANT_DIG
6fdc0f
+
6fdc0f
+SFtype
6fdc0f
+__floatundisf (UDWtype u)
6fdc0f
+{
6fdc0f
+  /* Protect against double-rounding error.
6fdc0f
+     Represent any low-order bits, that might be truncated in DFmode,
6fdc0f
+     by a bit that won't be lost.  The bit can go in anywhere below the
6fdc0f
+     rounding position of the SFmode.  A fixed mask and bit position
6fdc0f
+     handles all usual configurations.  It doesn't handle the case
6fdc0f
+     of 128-bit DImode, however.  */
6fdc0f
+  if (DF_SIZE < DI_SIZE
6fdc0f
+      && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE))
6fdc0f
+    {
6fdc0f
+#define REP_BIT ((UDWtype) 1 << (DI_SIZE - DF_SIZE))
6fdc0f
+      if (u >= ((UDWtype) 1 << DF_SIZE))
6fdc0f
+	{
6fdc0f
+	  if ((UDWtype) u & (REP_BIT - 1))
6fdc0f
+	    {
6fdc0f
+	      u &= ~ (REP_BIT - 1);
6fdc0f
+	      u |= REP_BIT;
6fdc0f
+	    }
6fdc0f
+	}
6fdc0f
+    }
6fdc0f
+  /* Do the calculation in DFmode
6fdc0f
+     so that we don't lose any of the precision of the high word
6fdc0f
+     while multiplying it.  */
6fdc0f
+  DFtype f = (UWtype) (u >> WORD_SIZE);
6fdc0f
+  f *= HIGH_HALFWORD_COEFF;
6fdc0f
+  f *= HIGH_HALFWORD_COEFF;
6fdc0f
+  f += (UWtype) (u & (HIGH_WORD_COEFF - 1));
6fdc0f
+
6fdc0f
+  return (SFtype) f;
6fdc0f
+}
6fdc0f
+#endif
6fdc0f
+
6fdc0f
 #if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
6fdc0f
 /* Reenable the normal types, in case limits.h needs them.  */
6fdc0f
 #undef char
6fdc0f
@@ -1475,6 +1569,246 @@ __fixunssfSI (SFtype a)
6fdc0f
 }
6fdc0f
 #endif
6fdc0f
 
6fdc0f
+/* Integer power helper used from __builtin_powi for non-constant
6fdc0f
+   exponents.  */
6fdc0f
+
6fdc0f
+#if defined(L_powisf2) || defined(L_powidf2) \
6fdc0f
+    || (defined(L_powixf2) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96) \
6fdc0f
+    || (defined(L_powitf2) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
6fdc0f
+# if defined(L_powisf2)
6fdc0f
+#  define TYPE SFtype
6fdc0f
+#  define NAME __powisf2
6fdc0f
+# elif defined(L_powidf2)
6fdc0f
+#  define TYPE DFtype
6fdc0f
+#  define NAME __powidf2
6fdc0f
+# elif defined(L_powixf2)
6fdc0f
+#  define TYPE XFtype
6fdc0f
+#  define NAME __powixf2
6fdc0f
+# elif defined(L_powitf2)
6fdc0f
+#  define TYPE TFtype
6fdc0f
+#  define NAME __powitf2
6fdc0f
+# endif
6fdc0f
+
6fdc0f
+#undef int
6fdc0f
+#undef unsigned
6fdc0f
+TYPE
6fdc0f
+NAME (TYPE x, int m)
6fdc0f
+{
6fdc0f
+  unsigned int n = m < 0 ? -m : m;
6fdc0f
+  TYPE y = n % 2 ? x : 1;
6fdc0f
+  while (n >>= 1)
6fdc0f
+    {
6fdc0f
+      x = x * x;
6fdc0f
+      if (n % 2)
6fdc0f
+	y = y * x;
6fdc0f
+    }
6fdc0f
+  return m < 0 ? 1/y : y;
6fdc0f
+}
6fdc0f
+
6fdc0f
+#endif
6fdc0f
+
6fdc0f
+#if defined(L_mulsc3) || defined(L_divsc3) \
6fdc0f
+    || defined(L_muldc3) || defined(L_divdc3) \
6fdc0f
+    || (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96 \
6fdc0f
+	&& (defined(L_mulxc3) || defined(L_divxc3))) \
6fdc0f
+    || (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128 \
6fdc0f
+	&& (defined(L_multc3) || defined(L_divtc3)))
6fdc0f
+
6fdc0f
+#undef float
6fdc0f
+#undef double
6fdc0f
+#undef long
6fdc0f
+
6fdc0f
+#if defined(L_mulsc3) || defined(L_divsc3)
6fdc0f
+# define MTYPE	SFtype
6fdc0f
+# define CTYPE	SCtype
6fdc0f
+# define MODE	sc
6fdc0f
+# define CEXT	f
6fdc0f
+# define NOTRUNC __FLT_EVAL_METHOD__ == 0
6fdc0f
+#elif defined(L_muldc3) || defined(L_divdc3)
6fdc0f
+# define MTYPE	DFtype
6fdc0f
+# define CTYPE	DCtype
6fdc0f
+# define MODE	dc
6fdc0f
+# if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64
6fdc0f
+#  define CEXT	l
6fdc0f
+#  define NOTRUNC 1
6fdc0f
+# else
6fdc0f
+#  define CEXT
6fdc0f
+#  define NOTRUNC __FLT_EVAL_METHOD__ == 0 || __FLT_EVAL_METHOD__ == 1
6fdc0f
+# endif
6fdc0f
+#elif defined(L_mulxc3) || defined(L_divxc3)
6fdc0f
+# define MTYPE	XFtype
6fdc0f
+# define CTYPE	XCtype
6fdc0f
+# define MODE	xc
6fdc0f
+# define CEXT	l
6fdc0f
+# define NOTRUNC 1
6fdc0f
+#elif defined(L_multc3) || defined(L_divtc3)
6fdc0f
+# define MTYPE	TFtype
6fdc0f
+# define CTYPE	TCtype
6fdc0f
+# define MODE	tc
6fdc0f
+# define CEXT	l
6fdc0f
+# define NOTRUNC 1
6fdc0f
+#else
6fdc0f
+# error
6fdc0f
+#endif
6fdc0f
+
6fdc0f
+#define CONCAT3(A,B,C)	_CONCAT3(A,B,C)
6fdc0f
+#define _CONCAT3(A,B,C)	A##B##C
6fdc0f
+
6fdc0f
+#define CONCAT2(A,B)	_CONCAT2(A,B)
6fdc0f
+#define _CONCAT2(A,B)	A##B
6fdc0f
+
6fdc0f
+/* All of these would be present in a full C99 implementation of <math.h>
6fdc0f
+   and <complex.h>.  Our problem is that only a few systems have such full
6fdc0f
+   implementations.  Further, libgcc_s.so isn't currently linked against
6fdc0f
+   libm.so, and even for systems that do provide full C99, the extra overhead
6fdc0f
+   of all programs using libgcc having to link against libm.  So avoid it.  */
6fdc0f
+
6fdc0f
+#define isnan(x)	__builtin_expect ((x) != (x), 0)
6fdc0f
+#define isfinite(x)	__builtin_expect (!isnan((x) - (x)), 1)
6fdc0f
+#define isinf(x)	__builtin_expect (!isnan(x) & !isfinite(x), 0)
6fdc0f
+
6fdc0f
+#define INFINITY	CONCAT2(__builtin_inf, CEXT) ()
6fdc0f
+#define I		1i
6fdc0f
+
6fdc0f
+/* Helpers to make the following code slightly less gross.  */
6fdc0f
+#define COPYSIGN	CONCAT2(__builtin_copysign, CEXT)
6fdc0f
+#define FABS		CONCAT2(__builtin_fabs, CEXT)
6fdc0f
+
6fdc0f
+/* Verify that MTYPE matches up with CEXT.  */
6fdc0f
+extern void *compile_type_assert[sizeof(INFINITY) == sizeof(MTYPE) ? 1 : -1];
6fdc0f
+
6fdc0f
+/* Ensure that we've lost any extra precision.  */
6fdc0f
+#if NOTRUNC
6fdc0f
+# define TRUNC(x)
6fdc0f
+#else
6fdc0f
+# define TRUNC(x)	__asm__ ("" : "=m"(x) : "m"(x))
6fdc0f
+#endif
6fdc0f
+
6fdc0f
+#if defined(L_mulsc3) || defined(L_muldc3) \
6fdc0f
+    || defined(L_mulxc3) || defined(L_multc3)
6fdc0f
+
6fdc0f
+CTYPE
6fdc0f
+CONCAT3(__mul,MODE,3) (MTYPE a, MTYPE b, MTYPE c, MTYPE d)
6fdc0f
+{
6fdc0f
+  MTYPE ac, bd, ad, bc, x, y;
6fdc0f
+
6fdc0f
+  ac = a * c;
6fdc0f
+  bd = b * d;
6fdc0f
+  ad = a * d;
6fdc0f
+  bc = b * c;
6fdc0f
+
6fdc0f
+  TRUNC (ac);
6fdc0f
+  TRUNC (bd);
6fdc0f
+  TRUNC (ad);
6fdc0f
+  TRUNC (bc);
6fdc0f
+
6fdc0f
+  x = ac - bd;
6fdc0f
+  y = ad + bc;
6fdc0f
+
6fdc0f
+  if (isnan (x) && isnan (y))
6fdc0f
+    {
6fdc0f
+      /* Recover infinities that computed as NaN + iNaN.  */
6fdc0f
+      _Bool recalc = 0;
6fdc0f
+      if (isinf (a) || isinf (b))
6fdc0f
+	{
6fdc0f
+	  /* z is infinite.  "Box" the infinity and change NaNs in
6fdc0f
+	     the other factor to 0.  */
6fdc0f
+	  a = COPYSIGN (isinf (a) ? 1 : 0, a);
6fdc0f
+	  b = COPYSIGN (isinf (b) ? 1 : 0, b);
6fdc0f
+	  if (isnan (c)) c = COPYSIGN (0, c);
6fdc0f
+	  if (isnan (d)) d = COPYSIGN (0, d);
6fdc0f
+          recalc = 1;
6fdc0f
+	}
6fdc0f
+     if (isinf (c) || isinf (d))
6fdc0f
+	{
6fdc0f
+	  /* w is infinite.  "Box" the infinity and change NaNs in
6fdc0f
+	     the other factor to 0.  */
6fdc0f
+	  c = COPYSIGN (isinf (c) ? 1 : 0, c);
6fdc0f
+	  d = COPYSIGN (isinf (d) ? 1 : 0, d);
6fdc0f
+	  if (isnan (a)) a = COPYSIGN (0, a);
6fdc0f
+	  if (isnan (b)) b = COPYSIGN (0, b);
6fdc0f
+	  recalc = 1;
6fdc0f
+	}
6fdc0f
+     if (!recalc
6fdc0f
+	  && (isinf (ac) || isinf (bd)
6fdc0f
+	      || isinf (ad) || isinf (bc)))
6fdc0f
+	{
6fdc0f
+	  /* Recover infinities from overflow by changing NaNs to 0.  */
6fdc0f
+	  if (isnan (a)) a = COPYSIGN (0, a);
6fdc0f
+	  if (isnan (b)) b = COPYSIGN (0, b);
6fdc0f
+	  if (isnan (c)) c = COPYSIGN (0, c);
6fdc0f
+	  if (isnan (d)) d = COPYSIGN (0, d);
6fdc0f
+	  recalc = 1;
6fdc0f
+	}
6fdc0f
+      if (recalc)
6fdc0f
+	{
6fdc0f
+	  x = INFINITY * (a * c - b * d);
6fdc0f
+	  y = INFINITY * (a * d + b * c);
6fdc0f
+	}
6fdc0f
+    }
6fdc0f
+
6fdc0f
+  return x + I * y;
6fdc0f
+}
6fdc0f
+#endif /* complex multiply */
6fdc0f
+
6fdc0f
+#if defined(L_divsc3) || defined(L_divdc3) \
6fdc0f
+    || defined(L_divxc3) || defined(L_divtc3)
6fdc0f
+
6fdc0f
+CTYPE
6fdc0f
+CONCAT3(__div,MODE,3) (MTYPE a, MTYPE b, MTYPE c, MTYPE d)
6fdc0f
+{
6fdc0f
+  MTYPE denom, ratio, x, y;
6fdc0f
+
6fdc0f
+  /* ??? We can get better behavior from logarithmic scaling instead of 
6fdc0f
+     the division.  But that would mean starting to link libgcc against
6fdc0f
+     libm.  We could implement something akin to ldexp/frexp as gcc builtins
6fdc0f
+     fairly easily...  */
6fdc0f
+  if (FABS (c) < FABS (d))
6fdc0f
+    {
6fdc0f
+      ratio = c / d;
6fdc0f
+      denom = (c * ratio) + d;
6fdc0f
+      x = ((a * ratio) + b) / denom;
6fdc0f
+      y = ((b * ratio) - a) / denom;
6fdc0f
+    }
6fdc0f
+  else
6fdc0f
+    {
6fdc0f
+      ratio = d / c;
6fdc0f
+      denom = (d * ratio) + c;
6fdc0f
+      x = ((b * ratio) + a) / denom;
6fdc0f
+      y = (b - (a * ratio)) / denom;
6fdc0f
+    }
6fdc0f
+
6fdc0f
+  /* Recover infinities and zeros that computed as NaN+iNaN; the only cases
6fdc0f
+     are nonzero/zero, infinite/finite, and finite/infinite.  */
6fdc0f
+  if (isnan (x) && isnan (y))
6fdc0f
+    {
6fdc0f
+      if (c == 0.0 && d == 0.0 && (!isnan (a) || !isnan (b)))
6fdc0f
+	{
6fdc0f
+	  x = COPYSIGN (INFINITY, c) * a;
6fdc0f
+	  y = COPYSIGN (INFINITY, c) * b;
6fdc0f
+	}
6fdc0f
+      else if ((isinf (a) || isinf (b)) && isfinite (c) && isfinite (d))
6fdc0f
+	{
6fdc0f
+	  a = COPYSIGN (isinf (a) ? 1 : 0, a);
6fdc0f
+	  b = COPYSIGN (isinf (b) ? 1 : 0, b);
6fdc0f
+	  x = INFINITY * (a * c + b * d);
6fdc0f
+	  y = INFINITY * (b * c - a * d);
6fdc0f
+	}
6fdc0f
+      else if ((isinf (c) || isinf (d)) && isfinite (a) && isfinite (b))
6fdc0f
+	{
6fdc0f
+	  c = COPYSIGN (isinf (c) ? 1 : 0, c);
6fdc0f
+	  d = COPYSIGN (isinf (d) ? 1 : 0, d);
6fdc0f
+	  x = 0.0 * (a * c + b * d);
6fdc0f
+	  y = 0.0 * (b * c - a * d);
6fdc0f
+	}
6fdc0f
+    }
6fdc0f
+
6fdc0f
+  return x + I * y;
6fdc0f
+}
6fdc0f
+#endif /* complex divide */
6fdc0f
+
6fdc0f
+#endif /* all complex float routines */
6fdc0f
+
6fdc0f
 /* From here on down, the routines use normal data types.  */
6fdc0f
 
6fdc0f
 #define SItype bogus_type