Index: gcc/c-family/c-cppbuiltin.c
===================================================================
--- gcc/c-family/c-cppbuiltin.c	(revision 215458)
+++ gcc/c-family/c-cppbuiltin.c	(working copy)
@@ -978,6 +978,30 @@ c_cpp_builtins (cpp_reader *pfile)
 	  else
 	    gcc_unreachable ();
 	  builtin_define_with_value (macro_name, suffix, 0);
+	  bool excess_precision = false;
+	  if (TARGET_FLT_EVAL_METHOD != 0
+	      && mode != TYPE_MODE (long_double_type_node)
+	      && (mode == TYPE_MODE (float_type_node)
+		  || mode == TYPE_MODE (double_type_node)))
+	    switch (TARGET_FLT_EVAL_METHOD)
+	      {
+	      case -1:
+	      case 2:
+		excess_precision = true;
+		break;
+
+	      case 1:
+		excess_precision = mode == TYPE_MODE (float_type_node);
+		break;
+
+	      default:
+		gcc_unreachable ();
+	      }
+	  macro_name = (char *) alloca (strlen (name)
+					+ sizeof ("__LIBGCC__EXCESS_"
+						  "PRECISION__"));
+	  sprintf (macro_name, "__LIBGCC_%s_EXCESS_PRECISION__", name);
+	  builtin_define_with_int_value (macro_name, excess_precision);
 	}
 
       /* For libgcc crtstuff.c and libgcc2.c.  */
Index: gcc/config/alpha/alpha.h
===================================================================
--- gcc/config/alpha/alpha.h	(revision 215458)
+++ gcc/config/alpha/alpha.h	(working copy)
@@ -203,14 +203,6 @@ extern enum alpha_fp_trap_mode alpha_fptm;
 #define DOUBLE_TYPE_SIZE 64
 #define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_128 ? 128 : 64)
 
-/* Define this to set long double type size to use in libgcc2.c, which can
-   not depend on target_flags.  */
-#ifdef __LONG_DOUBLE_128__
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
-#else
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
-#endif
-
 /* Work around target_flags dependency in ada/targtyps.c.  */
 #define WIDEST_HARDWARE_FP_SIZE 64
 
Index: gcc/config/i386/i386-interix.h
===================================================================
--- gcc/config/i386/i386-interix.h	(revision 215458)
+++ gcc/config/i386/i386-interix.h	(working copy)
@@ -140,8 +140,6 @@ do {									\
 /* Turn off long double being 96 bits.  */
 #undef LONG_DOUBLE_TYPE_SIZE
 #define LONG_DOUBLE_TYPE_SIZE 64
-#undef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
 
 #define IX86_NO_LIBGCC_TFMODE
 
Index: gcc/config/i386/i386.h
===================================================================
--- gcc/config/i386/i386.h	(revision 215458)
+++ gcc/config/i386/i386.h	(working copy)
@@ -694,16 +694,6 @@ extern const char *host_detect_local_cpu (int argc
 #define LONG_DOUBLE_TYPE_SIZE \
   (TARGET_LONG_DOUBLE_64 ? 64 : (TARGET_LONG_DOUBLE_128 ? 128 : 80))
 
-/* Define this to set long double type size to use in libgcc2.c, which can
-   not depend on target_flags.  */
-#ifdef __LONG_DOUBLE_64__
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
-#elif defined (__LONG_DOUBLE_128__)
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
-#else
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 80
-#endif
-
 #define WIDEST_HARDWARE_FP_SIZE 80
 
 #if defined (TARGET_BI_ARCH) || TARGET_64BIT_DEFAULT
Index: gcc/config/i386/rtemself.h
===================================================================
--- gcc/config/i386/rtemself.h	(revision 215458)
+++ gcc/config/i386/rtemself.h	(working copy)
@@ -32,11 +32,4 @@ along with GCC; see the file COPYING3.  If not see
 #undef LONG_DOUBLE_TYPE_SIZE
 #define LONG_DOUBLE_TYPE_SIZE (TARGET_80387 ? 80 : 64)
 
-#undef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
-#ifdef _SOFT_FLOAT
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
-#else
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 80
-#endif
-
 #define IX86_NO_LIBGCC_TFMODE
Index: gcc/config/ia64/ia64.h
===================================================================
--- gcc/config/ia64/ia64.h	(revision 215458)
+++ gcc/config/ia64/ia64.h	(working copy)
@@ -253,11 +253,7 @@ while (0)
    : TARGET_ABI_OPEN_VMS ? 64 \
    : 80)
 
-/* We always want the XFmode operations from libgcc2.c, except on VMS
-   where this yields references to unimplemented "insns".  */
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE  (TARGET_ABI_OPEN_VMS ? 64 : 80)
 
-
 #define DEFAULT_SIGNED_CHAR 1
 
 /* A C expression for a string describing the name of the data type to use for
Index: gcc/config/m68k/m68k.h
===================================================================
--- gcc/config/m68k/m68k.h	(revision 215458)
+++ gcc/config/m68k/m68k.h	(working copy)
@@ -280,14 +280,6 @@ along with GCC; see the file COPYING3.  If not see
 #define LONG_DOUBLE_TYPE_SIZE			\
   ((TARGET_COLDFIRE || TARGET_FIDOA) ? 64 : 80)
 
-/* We need to know the size of long double at compile-time in libgcc2.  */
-
-#if defined(__mcoldfire__) || defined(__mfido__)
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
-#else
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 80
-#endif
-
 /* Set the value of FLT_EVAL_METHOD in float.h.  When using 68040 fp
    instructions, we get proper intermediate rounding, otherwise we
    get extended precision results.  */
Index: gcc/config/m68k/netbsd-elf.h
===================================================================
--- gcc/config/m68k/netbsd-elf.h	(revision 215458)
+++ gcc/config/m68k/netbsd-elf.h	(working copy)
@@ -39,13 +39,6 @@ along with GCC; see the file COPYING3.  If not see
 #undef LONG_DOUBLE_TYPE_SIZE
 #define LONG_DOUBLE_TYPE_SIZE (TARGET_68020 ? 80 : 64)
 
-#undef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
-#ifdef __mc68010__
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
-#else
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 80
-#endif
-
 #undef SUBTARGET_EXTRA_SPECS
 #define SUBTARGET_EXTRA_SPECS \
   { "netbsd_entry_point",   NETBSD_ENTRY_POINT },
Index: gcc/config/mips/mips.h
===================================================================
--- gcc/config/mips/mips.h	(revision 215458)
+++ gcc/config/mips/mips.h	(working copy)
@@ -1399,15 +1399,6 @@ struct mips_cpu_info {
    support long double, we also want a 128-bit integer type.  */
 #define MAX_FIXED_MODE_SIZE LONG_DOUBLE_TYPE_SIZE
 
-#ifdef IN_LIBGCC2
-#if ((defined _ABIN32 && _MIPS_SIM == _ABIN32) \
-     || (defined _ABI64 && _MIPS_SIM == _ABI64))
-#  define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
-# else
-#  define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
-# endif
-#endif
-
 /* Width in bits of a pointer.  */
 #ifndef POINTER_SIZE
 #define POINTER_SIZE ((TARGET_LONG64 && TARGET_64BIT) ? 64 : 32)
Index: gcc/config/mips/n32-elf.h
===================================================================
--- gcc/config/mips/n32-elf.h	(revision 215458)
+++ gcc/config/mips/n32-elf.h	(working copy)
@@ -28,8 +28,3 @@ along with GCC; see the file COPYING3.  If not see
 /* Force n32 to use 64-bit long doubles.  */
 #undef LONG_DOUBLE_TYPE_SIZE
 #define LONG_DOUBLE_TYPE_SIZE 64
-
-#ifdef IN_LIBGCC2
-#undef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
-#endif
Index: gcc/config/msp430/msp430.h
===================================================================
--- gcc/config/msp430/msp430.h	(revision 215458)
+++ gcc/config/msp430/msp430.h	(working copy)
@@ -112,8 +112,6 @@ extern bool msp430x;
 #define DOUBLE_TYPE_SIZE 		64
 #define LONG_DOUBLE_TYPE_SIZE		64 /*DOUBLE_TYPE_SIZE*/
 
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE   64
-
 #define DEFAULT_SIGNED_CHAR		0
 
 #define STRICT_ALIGNMENT 		1
Index: gcc/config/rl78/rl78.h
===================================================================
--- gcc/config/rl78/rl78.h	(revision 215458)
+++ gcc/config/rl78/rl78.h	(working copy)
@@ -98,8 +98,6 @@
 #define DOUBLE_TYPE_SIZE 		32 /*64*/
 #define LONG_DOUBLE_TYPE_SIZE		64 /*DOUBLE_TYPE_SIZE*/
 
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE   64
-
 #define DEFAULT_SIGNED_CHAR		0
 
 #define STRICT_ALIGNMENT 		1
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 215458)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -820,14 +820,6 @@ extern unsigned char rs6000_recip_bits[];
    words.  */
 #define LONG_DOUBLE_TYPE_SIZE rs6000_long_double_type_size
 
-/* Define this to set long double type size to use in libgcc2.c, which can
-   not depend on target_flags.  */
-#ifdef __LONG_DOUBLE_128__
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
-#else
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
-#endif
-
 /* Work around rs6000_long_double_type_size dependency in ada/targtyps.c.  */
 #define WIDEST_HARDWARE_FP_SIZE 64
 
Index: gcc/config/rx/rx.h
===================================================================
--- gcc/config/rx/rx.h	(revision 215458)
+++ gcc/config/rx/rx.h	(working copy)
@@ -130,12 +130,6 @@
 #define DOUBLE_TYPE_SIZE 		(TARGET_64BIT_DOUBLES ? 64 : 32)
 #define LONG_DOUBLE_TYPE_SIZE		DOUBLE_TYPE_SIZE
 
-#ifdef __RX_32BIT_DOUBLES__
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE   32
-#else
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE   64
-#endif
-
 #define DEFAULT_SIGNED_CHAR		0
 
 /* RX load/store instructions can handle unaligned addresses.  */
Index: gcc/config/s390/s390.h
===================================================================
--- gcc/config/s390/s390.h	(revision 215458)
+++ gcc/config/s390/s390.h	(working copy)
@@ -252,14 +252,6 @@ enum processor_flags
 #define DOUBLE_TYPE_SIZE 64
 #define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_128 ? 128 : 64)
 
-/* Define this to set long double type size to use in libgcc2.c, which can
-   not depend on target_flags.  */
-#ifdef __LONG_DOUBLE_128__
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
-#else
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
-#endif
-
 /* Work around target_flags dependency in ada/targtyps.c.  */
 #define WIDEST_HARDWARE_FP_SIZE 64
 
Index: gcc/config/sparc/freebsd.h
===================================================================
--- gcc/config/sparc/freebsd.h	(revision 215458)
+++ gcc/config/sparc/freebsd.h	(working copy)
@@ -71,14 +71,6 @@ along with GCC; see the file COPYING3.  If not see
 #undef  LONG_DOUBLE_TYPE_SIZE
 #define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_128 ? 128 : 64)
 
-/* Define this to set long double type size to use in libgcc2.c, which can
-   not depend on target_flags.  */
-#if defined(__arch64__) || defined(__LONG_DOUBLE_128__)
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
-#else
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
-#endif
-
 /* Definitions for 64-bit SPARC running systems with ELF. */
 
 #define TARGET_ELF		1
Index: gcc/config/sparc/linux.h
===================================================================
--- gcc/config/sparc/linux.h	(revision 215458)
+++ gcc/config/sparc/linux.h	(working copy)
@@ -122,14 +122,6 @@ do {									\
    SPARC ABI says that long double is 4 words.  */
 #define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_128 ? 128 : 64)
 
-/* Define this to set long double type size to use in libgcc2.c, which can
-   not depend on target_flags.  */
-#ifdef __LONG_DOUBLE_128__
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
-#else
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
-#endif
-
 #undef DITF_CONVERSION_LIBFUNCS
 #define DITF_CONVERSION_LIBFUNCS 1
 
Index: gcc/config/sparc/linux64.h
===================================================================
--- gcc/config/sparc/linux64.h	(revision 215458)
+++ gcc/config/sparc/linux64.h	(working copy)
@@ -70,14 +70,6 @@ along with GCC; see the file COPYING3.  If not see
 #undef LONG_DOUBLE_TYPE_SIZE
 #define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_128 ? 128 : 64)
 
-/* Define this to set long double type size to use in libgcc2.c, which can
-   not depend on target_flags.  */
-#if defined(__arch64__) || defined(__LONG_DOUBLE_128__)
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
-#else
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
-#endif
-
 #undef CPP_SUBTARGET_SPEC
 #define CPP_SUBTARGET_SPEC "\
 %{posix:-D_POSIX_SOURCE} \
Index: gcc/config/sparc/netbsd-elf.h
===================================================================
--- gcc/config/sparc/netbsd-elf.h	(revision 215458)
+++ gcc/config/sparc/netbsd-elf.h	(working copy)
@@ -168,12 +168,6 @@ along with GCC; see the file COPYING3.  If not see
 #undef LONG_DOUBLE_TYPE_SIZE
 #define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_128 ? 128 : 64)
 
-#if defined(__arch64__) || defined(__LONG_DOUBLE_128__)
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
-#else
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
-#endif
-
 #undef  CC1_SPEC
 #if DEFAULT_ARCH32_P
 #define CC1_SPEC CC1_SPEC32
@@ -195,9 +189,6 @@ along with GCC; see the file COPYING3.  If not see
 #undef LONG_DOUBLE_TYPE_SIZE
 #define LONG_DOUBLE_TYPE_SIZE 128
 
-#undef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
-
 #undef  CC1_SPEC
 #define CC1_SPEC CC1_SPEC64
 
@@ -210,9 +201,6 @@ along with GCC; see the file COPYING3.  If not see
 #undef LONG_DOUBLE_TYPE_SIZE
 #define LONG_DOUBLE_TYPE_SIZE 64
 
-#undef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
-
 #undef  CC1_SPEC
 #define CC1_SPEC CC1_SPEC32
 
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	(revision 215458)
+++ gcc/doc/tm.texi	(working copy)
@@ -1542,13 +1542,6 @@ the target machine.  If you don't define this, the
 @code{BITS_PER_UNIT * 16}.
 @end defmac
 
-@defmac LIBGCC2_LONG_DOUBLE_TYPE_SIZE
-Define this macro if @code{LONG_DOUBLE_TYPE_SIZE} is not constant or
-if you want routines in @file{libgcc2.a} for a size other than
-@code{LONG_DOUBLE_TYPE_SIZE}.  If you don't define this, the
-default is @code{LONG_DOUBLE_TYPE_SIZE}.
-@end defmac
-
 @defmac LIBGCC2_GNU_PREFIX
 This macro corresponds to the @code{TARGET_LIBFUNC_GNU_PREFIX} target
 hook and should be defined if that hook is overriden to be true.  It
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in	(revision 215458)
+++ gcc/doc/tm.texi.in	(working copy)
@@ -1384,13 +1384,6 @@ the target machine.  If you don't define this, the
 @code{BITS_PER_UNIT * 16}.
 @end defmac
 
-@defmac LIBGCC2_LONG_DOUBLE_TYPE_SIZE
-Define this macro if @code{LONG_DOUBLE_TYPE_SIZE} is not constant or
-if you want routines in @file{libgcc2.a} for a size other than
-@code{LONG_DOUBLE_TYPE_SIZE}.  If you don't define this, the
-default is @code{LONG_DOUBLE_TYPE_SIZE}.
-@end defmac
-
 @defmac LIBGCC2_GNU_PREFIX
 This macro corresponds to the @code{TARGET_LIBFUNC_GNU_PREFIX} target
 hook and should be defined if that hook is overriden to be true.  It
Index: gcc/system.h
===================================================================
--- gcc/system.h	(revision 215458)
+++ gcc/system.h	(working copy)
@@ -936,7 +936,8 @@ extern void fancy_abort (const char *, int, const
 	EXTRA_CONSTRAINT_STR EXTRA_MEMORY_CONSTRAINT			   \
 	EXTRA_ADDRESS_CONSTRAINT CONST_DOUBLE_OK_FOR_CONSTRAINT_P	   \
 	CALLER_SAVE_PROFITABLE LARGEST_EXPONENT_IS_NORMAL		   \
-	ROUND_TOWARDS_ZERO SF_SIZE DF_SIZE XF_SIZE TF_SIZE LIBGCC2_TF_CEXT
+	ROUND_TOWARDS_ZERO SF_SIZE DF_SIZE XF_SIZE TF_SIZE LIBGCC2_TF_CEXT \
+	LIBGCC2_LONG_DOUBLE_TYPE_SIZE
 
 /* Hooks that are no longer used.  */
  #pragma GCC poison LANG_HOOKS_FUNCTION_MARK LANG_HOOKS_FUNCTION_FREE	\
Index: libgcc/dfp-bit.h
===================================================================
--- libgcc/dfp-bit.h	(revision 215458)
+++ libgcc/dfp-bit.h	(working copy)
@@ -34,19 +34,21 @@ see the files COPYING3 and COPYING.RUNTIME respect
 #include "tm.h"
 #include "libgcc_tm.h"
 
-#ifndef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
-#endif
-
 /* We need to know the size of long double that the C library supports.
    Don't use LIBGCC2_HAS_XF_MODE or LIBGCC2_HAS_TF_MODE here because
    some targets set both of those.  */
 
+#ifndef __LIBGCC_XF_MANT_DIG__
+#define __LIBGCC_XF_MANT_DIG__ 0
+#endif
 #define LONG_DOUBLE_HAS_XF_MODE \
-  (BITS_PER_UNIT == 8 && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80)
+  (__LDBL_MANT_DIG__ == __LIBGCC_XF_MANT_DIG__)
 
+#ifndef __LIBGCC_TF_MANT_DIG__
+#define __LIBGCC_TF_MANT_DIG__ 0
+#endif
 #define LONG_DOUBLE_HAS_TF_MODE \
-  (BITS_PER_UNIT == 8 && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
+  (__LDBL_MANT_DIG__ == __LIBGCC_TF_MANT_DIG__)
 
 /* Depending on WIDTH, define a number of macros:
 
Index: libgcc/libgcc2.c
===================================================================
--- libgcc/libgcc2.c	(revision 215458)
+++ libgcc/libgcc2.c	(working copy)
@@ -1866,29 +1866,25 @@ NAME (TYPE x, int m)
 # define CTYPE	SCtype
 # define MODE	sc
 # define CEXT	__LIBGCC_SF_FUNC_EXT__
-# define NOTRUNC __FLT_EVAL_METHOD__ == 0
+# define NOTRUNC __LIBGCC_SF_EXCESS_PRECISION__
 #elif defined(L_muldc3) || defined(L_divdc3)
 # define MTYPE	DFtype
 # define CTYPE	DCtype
 # define MODE	dc
 # define CEXT	__LIBGCC_DF_FUNC_EXT__
-# if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64
-#  define NOTRUNC 1
-# else
-#  define NOTRUNC __FLT_EVAL_METHOD__ == 0 || __FLT_EVAL_METHOD__ == 1
-# endif
+# define NOTRUNC __LIBGCC_DF_EXCESS_PRECISION__
 #elif defined(L_mulxc3) || defined(L_divxc3)
 # define MTYPE	XFtype
 # define CTYPE	XCtype
 # define MODE	xc
 # define CEXT	__LIBGCC_XF_FUNC_EXT__
-# define NOTRUNC 1
+# define NOTRUNC __LIBGCC_XF_EXCESS_PRECISION__
 #elif defined(L_multc3) || defined(L_divtc3)
 # define MTYPE	TFtype
 # define CTYPE	TCtype
 # define MODE	tc
 # define CEXT	__LIBGCC_TF_FUNC_EXT__
-# define NOTRUNC 1
+# define NOTRUNC __LIBGCC_TF_EXCESS_PRECISION__
 #else
 # error
 #endif
Index: libgcc/libgcc2.h
===================================================================
--- libgcc/libgcc2.h	(revision 215458)
+++ libgcc/libgcc2.h	(working copy)
@@ -34,10 +34,6 @@ extern void __clear_cache (char *, char *);
 extern void __eprintf (const char *, const char *, unsigned int, const char *)
   __attribute__ ((__noreturn__));
 
-#ifndef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
-#endif
-
 #ifdef __LIBGCC_HAS_SF_MODE__
 #define LIBGCC2_HAS_SF_MODE 1
 #else
