PATCH: Implement __float128 for ia64

H.J. Lu hjl.tools@gmail.com
Fri Jul 4 14:09:00 GMT 2008


On Thu, Jul 03, 2008 at 12:19:19PM -0700, H.J. Lu wrote:
> Hi,
> 
> This patch implements __float128 for ia64 with soft-fp. Tested on Linux/ia64.
> OK for trunk?
> 

Here is the updated patch with longlong.h ia64 update ported from GMP
4.2 by Uros. Tested on Linux/ia64, Linux/ia32 and Linux/x86-64. OK for
trunk?

Thanks.


H.J.
----
gcc/

2008-07-04  Uros Bizjak  <ubizjak@gmail.com>

	* longlong.h (sub_ddmmss): New for ia64. Ported from GMP 4.2.
	(umul_ppmm): Likewise.
	(count_leading_zeros): Likewise.
	(count_trailing_zeros): Likewise.
	(UMUL_TIME): Likewise.

2008-07-03  H.J. Lu  <hongjiu.lu@intel.com>

	PR target/36720
	* config/ia64/ia64.c (ia64_split_tmode): Fix typo in TImode
	constant for little endian.

2008-07-03  H.J. Lu  <hongjiu.lu@intel.com>

	* config.gcc: Add ia64/t-fprules-softfp soft-fp/t-softfp to
	tmake_file for ia64*-*-linux*.

	* config/ia64/ia64.c (ia64_soft_fp_init_libfuncs): New.
	(ia64_expand_compare): Use HPUX library for TFmode only for
	HPUX.
	(ia64_builtins): Add IA64_BUILTIN_COPYSIGNQ, IA64_BUILTIN_FABSQ
	and IA64_BUILTIN_INFQ.
	(ia64_init_builtins): Initialize __builtin_infq,
	__builtin_fabsq and __builtin_copysignq if not HPUX.
	(ia64_expand_builtin): Handle IA64_BUILTIN_COPYSIGNQ,
	IA64_BUILTIN_FABSQ and IA64_BUILTIN_INFQ.

	* config/ia64/lib1funcs.asm (__divtf3): Define only if
	SHARED is defined.
	(__fixtfti): Likewise.
	(__fixunstfti): Likewise.
	(__floattitf): Likewise.

	* config/ia64/libgcc-glibc.ver: New.
	* config/ia64/t-fprules-softfp: Likewise.
	* config/ia64/sfp-machine.h: Likewise.

	* config/ia64/linux.h (LIBGCC2_HAS_TF_MODE): New.
	(LIBGCC2_TF_CEXT): Likewise.
	(TF_SIZE): Likewise.
	(TARGET_INIT_LIBFUNCS): Likewise.

	* config/ia64/t-glibc: Add $(srcdir)/config/ia64/libgcc-glibc.ver
	to SHLIB_MAPFILES.

libgcc/

2008-07-03  H.J. Lu  <hongjiu.lu@intel.com>

	* config.host: Add ia64/t-fprules-softfp ia64/t-softfp-compat
	to tmake_file for ia64*-*-linux*.

	* Makefile.in (gen-hide-list): Ignore .*_compat and .*@.*.

	* config/ia64/__divxf3.asm: New.
	* config/ia64/_fixtfdi.asm: Likewise.
	* config/ia64/_fixunstfdi.asm: Likewise.
	* config/ia64/_floatditf.asm: Likewise.
	* config/ia64/t-fprules-softfp: Likewise.
	* config/ia64/t-softfp-compat: Likewise.
	* config/ia64/tf-signs.c: Likewise.

Index: libgcc/config.host
===================================================================
--- libgcc/config.host	(revision 3131)
+++ libgcc/config.host	(working copy)
@@ -346,7 +346,7 @@ ia64*-*-freebsd*)
 	;;
 ia64*-*-linux*)
 	extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtfastmath.o"
-	tmake_file="ia64/t-ia64"
+	tmake_file="ia64/t-ia64 ia64/t-fprules-softfp ia64/t-softfp-compat"
 	;;
 ia64*-*-hpux*)
 	;;
Index: libgcc/Makefile.in
===================================================================
--- libgcc/Makefile.in	(revision 3131)
+++ libgcc/Makefile.in	(working copy)
@@ -265,7 +265,9 @@ ASM_HIDDEN_OP = @asm_hidden_op@
 
 define gen-hide-list
 $(NM) -pg $< | \
-  $(AWK) 'NF == 3 && $$2 !~ /^[UN]$$/ { print "\t$(ASM_HIDDEN_OP)", $$3 }' > $@T
+  $(AWK) 'NF == 3 && $$2 !~ /^[UN]$$/ && $$3 !~ /.*_compat/ \
+         && $$3 !~ /.*@.*/ \
+	 { print "\t$(ASM_HIDDEN_OP)", $$3 }' > $@T
 mv -f $@T $@
 endef
 else
Index: libgcc/config/ia64/__divxf3.asm
===================================================================
--- libgcc/config/ia64/__divxf3.asm	(revision 0)
+++ libgcc/config/ia64/__divxf3.asm	(revision 3132)
@@ -0,0 +1,11 @@
+#ifdef SHARED
+#define __divtf3 __divtf3_compat
+#endif
+
+#define L__divxf3
+#include "config/ia64/lib1funcs.asm"
+
+#ifdef SHARED
+#undef __divtf3
+.symver __divtf3_compat, __divtf3@GCC_3.0
+#endif
Index: libgcc/config/ia64/t-fprules-softfp
===================================================================
--- libgcc/config/ia64/t-fprules-softfp	(revision 0)
+++ libgcc/config/ia64/t-fprules-softfp	(revision 3132)
@@ -0,0 +1,2 @@
+# Provide fallbacks for __builtin_copysignq and __builtin_fabsq.
+LIB2ADD += $(srcdir)/config/ia64/tf-signs.c
Index: libgcc/config/ia64/_fixunstfdi.asm
===================================================================
--- libgcc/config/ia64/_fixunstfdi.asm	(revision 0)
+++ libgcc/config/ia64/_fixunstfdi.asm	(revision 3132)
@@ -0,0 +1,11 @@
+#ifdef SHARED
+#define __fixunstfti __fixunstfti_compat
+#endif
+
+#define L_fixunstfdi
+#include "config/ia64/lib1funcs.asm"
+
+#ifdef SHARED
+#undef __fixunstfti
+.symver __fixunstfti_compat, __fixunstfti@GCC_3.0
+#endif
Index: libgcc/config/ia64/t-softfp-compat
===================================================================
--- libgcc/config/ia64/t-softfp-compat	(revision 0)
+++ libgcc/config/ia64/t-softfp-compat	(revision 3132)
@@ -0,0 +1,7 @@
+# Filter out the following TImode functions and provide backward binary
+# compatibility.
+# Replace __dvxf3 _fixtfdi _fixunstfdi _floatditf
+libgcc1-tf-functions = __divxf3  _fixtfdi _fixunstfdi _floatditf
+LIB1ASMFUNCS := $(filter-out $(libgcc1-tf-functions), $(LIB1ASMFUNCS))
+libgcc1-tf-compats = $(addsuffix .asm, $(libgcc1-tf-functions))
+LIB2ADD += $(addprefix $(srcdir)/config/ia64/, $(libgcc1-tf-compats))
Index: libgcc/config/ia64/_floatditf.asm
===================================================================
--- libgcc/config/ia64/_floatditf.asm	(revision 0)
+++ libgcc/config/ia64/_floatditf.asm	(revision 3132)
@@ -0,0 +1,11 @@
+#ifdef SHARED
+#define __floattitf __floattitf_compat
+#endif
+
+#define L_floatditf
+#include "config/ia64/lib1funcs.asm"
+
+#ifdef SHARED
+#undef __floattitf
+.symver __floattitf_compat, __floattitf@GCC_3.0
+#endif
Index: libgcc/config/ia64/_fixtfdi.asm
===================================================================
--- libgcc/config/ia64/_fixtfdi.asm	(revision 0)
+++ libgcc/config/ia64/_fixtfdi.asm	(revision 3132)
@@ -0,0 +1,11 @@
+#ifdef SHARED
+#define __fixtfti __fixtfti_compat
+#endif
+
+#define L_fixtfdi
+#include "config/ia64/lib1funcs.asm"
+
+#ifdef SHARED
+#undef __fixtfti
+.symver __fixtfti_compat, __fixtfti@GCC_3.0
+#endif
Index: libgcc/config/ia64/tf-signs.c
===================================================================
--- libgcc/config/ia64/tf-signs.c	(revision 0)
+++ libgcc/config/ia64/tf-signs.c	(revision 3132)
@@ -0,0 +1,62 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file.  (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+GCC 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 General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
+
+union _FP_UNION_Q
+{
+   __float128 flt;
+   struct 
+   {
+      unsigned long frac1 : 64;
+      unsigned long frac0 : 48;
+      unsigned exp : 15;
+      unsigned sign : 1;
+   } bits __attribute__((packed));
+};
+
+__float128
+__copysigntf3 (__float128 a, __float128 b)
+{
+  union _FP_UNION_Q A, B;
+
+  A.flt = a;
+  B.flt = b;
+  A.bits.sign = B.bits.sign;
+
+  return A.flt;
+}
+
+__float128
+__fabstf2 (__float128 a)
+{
+  union _FP_UNION_Q A;
+
+  A.flt = a;
+  A.bits.sign = 0;
+
+  return A.flt;
+}
Index: libgcc/ChangeLog.float128
===================================================================
Index: gcc/ChangeLog.float128
===================================================================
Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(revision 3131)
+++ gcc/config.gcc	(working copy)
@@ -2979,6 +2979,9 @@ case ${target} in
 	i[34567]86-*-linux* | x86_64-*-linux*)
 		tmake_file="${tmake_file} i386/t-fprules-softfp soft-fp/t-softfp i386/t-linux"
 		;;
+	ia64*-*-linux*)
+		tmake_file="${tmake_file} ia64/t-fprules-softfp soft-fp/t-softfp"
+		;;
 
 	mips*-*-*)
 		if test x$gnu_ld = xyes
Index: gcc/config/ia64/t-glibc
===================================================================
--- gcc/config/ia64/t-glibc	(revision 3131)
+++ gcc/config/ia64/t-glibc	(working copy)
@@ -1,3 +1,5 @@
 # Use system libunwind library on IA-64 GLIBC based system.
 LIB2ADDEH = $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c \
   $(srcdir)/unwind-compat.c
+
+SHLIB_MAPFILES += $(srcdir)/config/ia64/libgcc-glibc.ver
Index: gcc/config/ia64/linux.h
===================================================================
--- gcc/config/ia64/linux.h	(revision 3131)
+++ gcc/config/ia64/linux.h	(working copy)
@@ -59,3 +59,13 @@ do {						\
 #define LINK_EH_SPEC ""
 
 #define MD_UNWIND_SUPPORT "config/ia64/linux-unwind.h"
+
+/* Put all *tf routines in libgcc.  */
+#undef LIBGCC2_HAS_TF_MODE
+#define LIBGCC2_HAS_TF_MODE 1
+#undef LIBGCC2_TF_CEXT
+#define LIBGCC2_TF_CEXT q
+#define TF_SIZE 113
+
+#undef TARGET_INIT_LIBFUNCS
+#define TARGET_INIT_LIBFUNCS ia64_soft_fp_init_libfuncs
Index: gcc/config/ia64/lib1funcs.asm
===================================================================
--- gcc/config/ia64/lib1funcs.asm	(revision 3131)
+++ gcc/config/ia64/lib1funcs.asm	(working copy)
@@ -38,10 +38,12 @@
 	.text
 	.align 16
 	.global __divxf3
-	.global __divtf3
 	.proc __divxf3
 __divxf3:
+#ifdef SHARED
+	.global __divtf3
 __divtf3:
+#endif
 	cmp.eq p7, p0 = r0, r0
 	frcpa.s0 f10, p6 = farg0, farg1
 	;;
@@ -757,6 +759,7 @@ __ia64_trampoline:
 	.endp __ia64_trampoline
 #endif
 
+#ifdef SHARED
 // Thunks for backward compatibility.
 #ifdef L_fixtfdi
 	.text
@@ -781,7 +784,7 @@ __fixunstfti:
 	}
 	.endp __fixunstfti
 #endif
-#if L_floatditf
+#ifdef L_floatditf
 	.align 16
 	.global __floattitf
 	.proc __floattitf
@@ -792,3 +795,4 @@ __floattitf:
 	}
 	.endp __floattitf
 #endif
+#endif
Index: gcc/config/ia64/sfp-machine.h
===================================================================
--- gcc/config/ia64/sfp-machine.h	(revision 0)
+++ gcc/config/ia64/sfp-machine.h	(revision 3132)
@@ -0,0 +1,116 @@
+#define _FP_W_TYPE_SIZE		64
+#define _FP_W_TYPE		unsigned long
+#define _FP_WS_TYPE		signed long
+#define _FP_I_TYPE		long
+
+typedef int TItype __attribute__ ((mode (TI)));
+typedef unsigned int UTItype __attribute__ ((mode (TI)));
+
+#define TI_BITS (__CHAR_BIT__ * (int)sizeof(TItype))
+
+/* The type of the result of a floating point comparison.  This must
+   match `__libgcc_cmp_return__' in GCC for the target.  */
+typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
+#define CMPtype __gcc_CMPtype
+
+#define _FP_MUL_MEAT_Q(R,X,Y)                           \
+  _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_Q(R,X,Y)   _FP_DIV_MEAT_2_udiv(Q,R,X,Y)
+
+#define _FP_NANFRAC_S		_FP_QNANBIT_S
+#define _FP_NANFRAC_D		_FP_QNANBIT_D
+#define _FP_NANFRAC_E		_FP_QNANBIT_E, 0
+#define _FP_NANFRAC_Q		_FP_QNANBIT_Q, 0
+#define _FP_NANSIGN_S		1
+#define _FP_NANSIGN_D		1
+#define _FP_NANSIGN_E		1
+#define _FP_NANSIGN_Q		1
+
+#define _FP_KEEPNANFRACP 1
+
+/* Here is something Intel misdesigned: the specs don't define
+   the case where we have two NaNs with same mantissas, but
+   different sign. Different operations pick up different NaNs.  */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)			\
+  do {								\
+    if (_FP_FRAC_GT_##wc(X, Y)					\
+	|| (_FP_FRAC_EQ_##wc(X,Y) && (OP == '+' || OP == '*')))	\
+      {								\
+	R##_s = X##_s;						\
+        _FP_FRAC_COPY_##wc(R,X);				\
+      }								\
+    else							\
+      {								\
+	R##_s = Y##_s;						\
+        _FP_FRAC_COPY_##wc(R,Y);				\
+      }								\
+    R##_c = FP_CLS_NAN;						\
+  } while (0)
+
+#define FP_EX_INVALID		0x01
+#define FP_EX_DENORM		0x02
+#define FP_EX_DIVZERO		0x04
+#define FP_EX_OVERFLOW		0x08
+#define FP_EX_UNDERFLOW		0x10
+#define FP_EX_INEXACT		0x20
+
+#define FP_HANDLE_EXCEPTIONS						\
+  do {									\
+    double tmp, dummy;							\
+    if (_fex & FP_EX_INVALID)						\
+      {									\
+	tmp = 0.0;							\
+	__asm__ __volatile__ ("frcpa.s0 %0,p1=f0,f0"			\
+			      : "=f" (tmp) : : "p1" );			\
+      }									\
+    if (_fex & FP_EX_DIVZERO)						\
+      {									\
+	__asm__ __volatile__ ("frcpa.s0 %0,p1=f1,f0"			\
+			      : "=f" (tmp) : : "p1" );			\
+      }									\
+    if (_fex & FP_EX_OVERFLOW)						\
+      {									\
+	dummy = __DBL_MAX__;						\
+	__asm__ __volatile__ ("fadd.d.s0 %0=%1,%1"			\
+			      : "=f" (dummy) : "0" (dummy));		\
+      }									\
+    if (_fex & FP_EX_UNDERFLOW)						\
+      {									\
+	dummy = __DBL_MIN__;						\
+	__asm__ __volatile__ ("fnma.d.s0 %0=%1,%1,f0"			\
+			      : "=f" (tmp) : "f" (dummy));		\
+      }									\
+    if (_fex & FP_EX_INEXACT)						\
+      {									\
+	dummy = __DBL_MAX__;						\
+	__asm__ __volatile__ ("fsub.d.s0 %0=%1,f1"			\
+			      : "=f" (dummy) : "0" (dummy));		\
+      }									\
+  } while (0)
+
+#define FP_RND_NEAREST		0
+#define FP_RND_ZERO		0xc00L
+#define FP_RND_PINF		0x800L
+#define FP_RND_MINF		0x400L
+
+#define _FP_DECL_EX \
+  unsigned long int _fpsr __attribute__ ((unused)) = FP_RND_NEAREST
+
+#define FP_INIT_ROUNDMODE			\
+  do {						\
+    __asm__ __volatile__ ("mov.m %0=ar.fpsr"	\
+			  : "=r" (_fpsr));	\
+  } while (0)
+
+#define FP_ROUNDMODE		(_fpsr & 0xc00L)
+
+#define	__LITTLE_ENDIAN	1234
+#define	__BIG_ENDIAN	4321
+
+#define __BYTE_ORDER __LITTLE_ENDIAN
+
+/* Define ALIASNAME as a strong alias for NAME.  */
+#define strong_alias(name, aliasname) _strong_alias(name, aliasname)
+#define _strong_alias(name, aliasname) \
+  extern __typeof (name) aliasname __attribute__ ((alias (#name)));
Index: gcc/config/ia64/t-fprules-softfp
===================================================================
--- gcc/config/ia64/t-fprules-softfp	(revision 0)
+++ gcc/config/ia64/t-fprules-softfp	(revision 3132)
@@ -0,0 +1,6 @@
+softfp_float_modes := tf
+softfp_int_modes := si di ti
+softfp_extensions := sftf dftf xftf
+softfp_truncations := tfsf tfdf tfxf
+softfp_machine_header := ia64/sfp-machine.h
+softfp_exclude_libgcc2 := n
Index: gcc/config/ia64/ia64.c
===================================================================
--- gcc/config/ia64/ia64.c	(revision 3131)
+++ gcc/config/ia64/ia64.c	(working copy)
@@ -270,6 +270,8 @@ static void ia64_sysv4_init_libfuncs (vo
      ATTRIBUTE_UNUSED;
 static void ia64_vms_init_libfuncs (void)
      ATTRIBUTE_UNUSED;
+static void ia64_soft_fp_init_libfuncs (void)
+     ATTRIBUTE_UNUSED;
 
 static tree ia64_handle_model_attribute (tree *, tree, tree, int, bool *);
 static tree ia64_handle_version_id_attribute (tree *, tree, tree, int, bool *);
@@ -1119,8 +1121,8 @@ ia64_split_tmode (rtx out[2], rtx in, bo
 	    }
 	  else
 	    {
-	      p[0] = (((unsigned HOST_WIDE_INT) l[3]) << 32) + l[2];
-	      p[1] = (((unsigned HOST_WIDE_INT) l[1]) << 32) + l[0];
+	      p[0] = (((unsigned HOST_WIDE_INT) l[1]) << 32) + l[0];
+	      p[1] = (((unsigned HOST_WIDE_INT) l[3]) << 32) + l[2];
 	    }
 	  out[0] = GEN_INT (p[0]);
 	  out[1] = GEN_INT (p[1]);
@@ -1480,7 +1482,7 @@ ia64_expand_compare (enum rtx_code code,
   /* HPUX TFmode compare requires a library call to _U_Qfcmp, which takes a
      magic number as its third argument, that indicates what to do.
      The return value is an integer to be compared against zero.  */
-  else if (GET_MODE (op0) == TFmode)
+  else if (TARGET_HPUX && GET_MODE (op0) == TFmode)
     {
       enum qfcmp_magic {
 	QCMP_INV = 1,	/* Raise FP_INVALID on SNaN as a side effect.  */
@@ -9233,7 +9235,10 @@ process_for_unwind_directive (FILE *asm_
 enum ia64_builtins
 {
   IA64_BUILTIN_BSP,
-  IA64_BUILTIN_FLUSHRS
+  IA64_BUILTIN_COPYSIGNQ,
+  IA64_BUILTIN_FABSQ,
+  IA64_BUILTIN_FLUSHRS,
+  IA64_BUILTIN_INFQ
 };
 
 void
@@ -9257,10 +9262,35 @@ ia64_init_builtins (void)
   /* The __float128 type.  */
   if (!TARGET_HPUX)
     {
+      tree ftype, decl;
       tree float128_type = make_node (REAL_TYPE);
+
       TYPE_PRECISION (float128_type) = 128;
       layout_type (float128_type);
       (*lang_hooks.types.register_builtin_type) (float128_type, "__float128");
+
+      /* TFmode support builtins.  */
+      ftype = build_function_type (float128_type, void_list_node);
+      add_builtin_function ("__builtin_infq", ftype,
+			    IA64_BUILTIN_INFQ, BUILT_IN_MD,
+			    NULL, NULL_TREE);
+
+      ftype = build_function_type_list (float128_type,
+					float128_type,
+					NULL_TREE);
+      decl = add_builtin_function ("__builtin_fabsq", ftype,
+				   IA64_BUILTIN_FABSQ, BUILT_IN_MD,
+				   "__fabstf2", NULL_TREE);
+      TREE_READONLY (decl) = 1;
+
+      ftype = build_function_type_list (float128_type,
+					float128_type,
+					float128_type,
+					NULL_TREE);
+      decl = add_builtin_function ("__builtin_copysignq", ftype,
+				   IA64_BUILTIN_COPYSIGNQ, BUILT_IN_MD,
+				   "__copysigntf3", NULL_TREE);
+      TREE_READONLY (decl) = 1;
     }
   else
     /* Under HPUX, this is a synonym for "long double".  */
@@ -9318,8 +9348,29 @@ ia64_expand_builtin (tree exp, rtx targe
       emit_insn (gen_flushrs ());
       return const0_rtx;
 
+    case IA64_BUILTIN_INFQ:
+      {
+	REAL_VALUE_TYPE inf;
+	rtx tmp;
+
+	real_inf (&inf);
+	tmp = CONST_DOUBLE_FROM_REAL_VALUE (inf, mode);
+
+	tmp = validize_mem (force_const_mem (mode, tmp));
+
+	if (target == 0)
+	  target = gen_reg_rtx (mode);
+
+	emit_move_insn (target, tmp);
+	return target;
+      }
+
+    case IA64_BUILTIN_FABSQ:
+    case IA64_BUILTIN_COPYSIGNQ:
+      return expand_call (exp, target, ignore);
+
     default:
-      break;
+      gcc_unreachable ();
     }
 
   return NULL_RTX;
@@ -9482,6 +9533,13 @@ ia64_sysv4_init_libfuncs (void)
   /* We leave out _U_Qfmin, _U_Qfmax and _U_Qfabs since soft-fp in
      glibc doesn't have them.  */
 }
+
+/* Use soft-fp.  */
+
+static void
+ia64_soft_fp_init_libfuncs (void)
+{
+}
 
 /* For HPUX, it is illegal to have relocations in shared segments.  */
 
@@ -9732,7 +9790,7 @@ ia64_scalar_mode_supported_p (enum machi
       return true;
 
     case TFmode:
-      return TARGET_HPUX;
+      return true;
 
     default:
       return false;
Index: gcc/config/ia64/libgcc-glibc.ver
===================================================================
--- gcc/config/ia64/libgcc-glibc.ver	(revision 0)
+++ gcc/config/ia64/libgcc-glibc.ver	(revision 3132)
@@ -0,0 +1,79 @@
+# 128 bit long double support was introduced with GCC 4.4.0. These lines
+# make the symbols to get @@GCC_4.4.0 attached.
+
+%exclude {
+  __addtf3
+  __divtc3
+  __divtf3
+  __eqtf2
+  __extenddftf2
+  __extendsftf2
+  __extendxftf2
+  __fixtfdi
+  __fixtfsi
+  __fixtfti
+  __fixunstfdi
+  __fixunstfsi
+  __fixunstfti
+  __floatditf
+  __floatsitf
+  __floattitf
+  __floatunditf
+  __floatunsitf
+  __floatuntitf
+  __getf2
+  __gttf2
+  __letf2
+  __lttf2
+  __multc3
+  __multf3
+  __negtf2
+  __netf2
+  __powitf2
+  __subtf3
+  __trunctfdf2
+  __trunctfsf2
+  __trunctfxf2
+  __unordtf2
+}
+
+# Those TF functions are the aliases of the XF functions before gcc 3.4.
+GCC_3.0 {
+  __divtf3
+  __fixtfti
+  __fixunstfti
+  __floattitf
+}
+
+GCC_4.4.0 {
+  __addtf3
+  __copysigntf3
+  __divtc3
+  __divtf3
+  __eqtf2
+  __extenddftf2
+  __extendsftf2
+  __fabstf2
+  __fixtfdi
+  __fixtfsi
+  __fixunstfdi
+  __fixunstfsi
+  __floatditf
+  __floatsitf
+  __floatunditf
+  __floatunsitf
+  __getf2
+  __gttf2
+  __letf2
+  __lttf2
+  __multc3
+  __multf3
+  __negtf2
+  __netf2
+  __powitf2
+  __subtf3
+  __trunctfdf2
+  __trunctfsf2
+  __trunctfxf2
+  __unordtf2
+}
Index: gcc/longlong.h
===================================================================
--- gcc/longlong.h	(revision 3120)
+++ gcc/longlong.h	(working copy)
@@ -414,6 +414,55 @@ UDItype __umulsidi3 (USItype, USItype);
     __w; })
 #endif /* __i960__ */
 
+#if defined (__ia64) && W_TYPE_SIZE == 64
+/* This form encourages gcc (pre-release 3.4 at least) to emit predicated
+   "sub r=r,r" and "sub r=r,r,1", giving a 2 cycle latency.  The generic
+   code using "al<bl" arithmetically comes out making an actual 0 or 1 in a
+   register, which takes an extra cycle.  */
+#define sub_ddmmss(sh, sl, ah, al, bh, bl)				\
+  do {									\
+    UWtype __x;								\
+    __x = (al) - (bl);							\
+    if ((al) < (bl))							\
+      (sh) = (ah) - (bh) - 1;						\
+    else								\
+      (sh) = (ah) - (bh);						\
+    (sl) = __x;								\
+  } while (0)
+
+/* Do both product parts in assembly, since that gives better code with
+   all gcc versions.  Some callers will just use the upper part, and in
+   that situation we waste an instruction, but not any cycles.  */
+#define umul_ppmm(ph, pl, m0, m1)					\
+  __asm__ ("xma.hu %0 = %2, %3, f0\n\txma.l %1 = %2, %3, f0"		\
+	   : "=&f" (ph), "=f" (pl)					\
+	   : "f" (m0), "f" (m1))
+#define count_leading_zeros(count, x)					\
+  do {									\
+    UWtype _x = (x), _y, _a, _c;					\
+    __asm__ ("mux1 %0 = %1, @rev" : "=r" (_y) : "r" (_x));		\
+    __asm__ ("czx1.l %0 = %1" : "=r" (_a) : "r" (-_y | _y));		\
+    _c = (_a - 1) << 3;							\
+    _x >>= _c;								\
+    if (_x >= 1 << 4)							\
+      _x >>= 4, _c += 4;						\
+    if (_x >= 1 << 2)							\
+      _x >>= 2, _c += 2;						\
+    _c += _x >> 1;							\
+    (count) =  W_TYPE_SIZE - 1 - _c;					\
+  } while (0)
+/* similar to what gcc does for __builtin_ffs, but 0 based rather than 1
+   based, and we don't need a special case for x==0 here */
+#define count_trailing_zeros(count, x)					\
+  do {									\
+    UWtype __ctz_x = (x);						\
+    __asm__ ("popcnt %0 = %1"						\
+	     : "=r" (count)						\
+	     : "r" ((__ctz_x-1) & ~__ctz_x));				\
+  } while (0)
+#define UMUL_TIME 14
+#endif
+
 #if defined (__M32R__) && W_TYPE_SIZE == 32
 #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
   /* The cmp clears the condition bit.  */ \



More information about the Gcc-patches mailing list