diff mbox

Remove LIBGCC2_HAS_?F_MODE target macros

Message ID Pine.LNX.4.64.1409120121460.5583@digraph.polyomino.org.uk
State New
Headers show

Commit Message

Joseph Myers Sept. 12, 2014, 1:22 a.m. UTC
This patch removes the LIBGCC2_HAS_{SF,DF,XF,TF}_MODE target macros,
replacing them by predefines with -fbuilding-libgcc, together with a
target hook that can influence those predefines when needed.

The new default is that a floating-point mode is supported in libgcc
if (a) it passes the scalar_mode_supported_p hook (otherwise it's not
plausible for it to be supported in libgcc) and (b) it's one of those
four modes (since those are the modes for which libgcc hardcodes the
possibility of support).  The target hook can override the default
choice (in either direction) for modes that pass
scalar_mode_supported_p (although overriding in the direction of
returning true when the default would return false only makes sense if
all relevant functions are specially defined in libgcc for that
particular target).

The previous default settings depended on various settings such as
LIBGCC2_LONG_DOUBLE_TYPE_SIZE, as well as targets defining the above
target macros if the default wasn't correct.

The default scalar_mode_supported_p only declares a floating-point
mode to be supported if it matches one of float / double / long
double.  This means that in most cases where a mode is only supported
conditionally in libgcc (TFmode only supported if it's the mode of
long double, most commonly), the default gets things right.  Overrides
were needed in the following cases:

* SFmode would always have been supported in libgcc (the condition was
  BITS_PER_UNIT == 8, true for all current targets), but pdp11
  defaults to 64-bit float, and in that case SFmode would fail
  scalar_mode_supported_p.  I don't know if libgcc actually built for
  pdp11 (and the port may well no longer be being used), but this
  patch adds a scalar_mode_supported_p hook to it to ensure SFmode is
  treated as supported.

* Certain i386 and ia64 targets need the new hook to match the
  existing cases for when XFmode or TFmode support is present in
  libgcc.  For i386, the hook can always declare XFmode to be
  supported - the cases where it's not are the cases where long double
  is TFmode, in which case XFmode fails scalar_mode_supported_p[*] -
  but TFmode support needs to be conditional.  (And of the targets not
  defining LIBGCC2_HAS_TF_MODE before this patch, some defined
  LONG_DOUBLE_TYPE_SIZE to 64, so ensuring LIBGCC2_HAS_TF_MODE would
  always be false, while others did not define it, so allowing it to
  be true in the -mlong-double-128 case.  This patch matches that
  logic, although I suspect all the latter targets would have been
  broken if you tried to enable -mlong-double-128 by default, for lack
  of the soft-fp TFmode support in libgcc, which is separately
  configured.)

  [*] I don't know if it's deliberate not to support __float80 at all
  with -mlong-double-128.

In order to implement the default version of the new hook,
insn-modes.h was made to contain macros such as HAVE_TFmode for each
machine mode, so the default hook can contain conditionals on whether
XFmode and TFmode exist (to match the hardcoding of a list of modes in
libgcc).  This is also used in fortran/trans-types.c; previously it
had a conditional on defined(LIBGCC2_HAS_TF_MODE) (a bit dubious,
since it ignored the value of the macro), which is replaced by testing
defined(HAVE_TFmode), in conjunction with requiring
targetm.libgcc_floating_mode_supported_p.

(Fortran is testing something stronger than that hook: not only is
libgcc support required, but also libm or equivalent.  Thus, it has a
test for ENABLE_LIBQUADMATH_SUPPORT in the case that the mode is
TFmode and that's not the same as any of the three standard types.
The old and new tests are intended to accept exactly the same set of
modes for all targets.)

Apart from the four target macros eliminated by this patch, it gets us
closer to eliminating LIBGCC2_LONG_DOUBLE_TYPE_SIZE as well, though a
few more places using that macro need changing first.

Bootstrapped with no regressions on x86_64-unknown-linux-gnu; also
built cc1 for crosses to ia64-elf and pdp11-none as a minimal test of
changes for those targets.  OK to commit?

gcc:
2014-09-11  Joseph Myers  <joseph@codesourcery.com>

	* target.def (libgcc_floating_mode_supported_p): New hook.
	* targhooks.c (default_libgcc_floating_mode_supported_p): New
	function.
	* targhooks.h (default_libgcc_floating_mode_supported_p): Declare.
	* doc/tm.texi.in (LIBGCC2_HAS_DF_MODE, LIBGCC2_HAS_XF_MODE)
	(LIBGCC2_HAS_TF_MODE): Remove.
	(TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P): New @hook.
	* doc/tm.texi: Regenerate.
	* genmodes.c (emit_insn_modes_h): Define HAVE_%smode for each
	machine mode.
	* system.h (LIBGCC2_HAS_SF_MODE, LIBGCC2_HAS_DF_MODE)
	(LIBGCC2_HAS_XF_MODE, LIBGCC2_HAS_TF_MODE): Poison.
	* config/i386/cygming.h (LIBGCC2_HAS_TF_MODE): Remove.
	* config/i386/darwin.h (LIBGCC2_HAS_TF_MODE): Remove.
	* config/i386/djgpp.h (IX86_MAYBE_NO_LIBGCC_TFMODE): Define.
	* config/i386/dragonfly.h (LIBGCC2_HAS_TF_MODE): Remove.
	* config/i386/freebsd.h (LIBGCC2_HAS_TF_MODE): Remove.
	* config/i386/gnu-user-common.h (LIBGCC2_HAS_TF_MODE): Remove.
	* config/i386/i386-interix.h (IX86_NO_LIBGCC_TFMODE): Define.
	* config/i386/i386.c (ix86_libgcc_floating_mode_supported_p): New
	function.
	(TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P): Define.
	* config/i386/i386elf.h (IX86_MAYBE_NO_LIBGCC_TFMODE): Define.
	* config/i386/lynx.h (IX86_MAYBE_NO_LIBGCC_TFMODE): Define.
	* config/i386/netbsd-elf.h (IX86_MAYBE_NO_LIBGCC_TFMODE): Define.
	* config/i386/netbsd64.h (IX86_MAYBE_NO_LIBGCC_TFMODE): Define.
	* config/i386/nto.h (IX86_MAYBE_NO_LIBGCC_TFMODE): Define.
	* config/i386/openbsd.h (IX86_MAYBE_NO_LIBGCC_TFMODE): Define.
	* config/i386/openbsdelf.h (LIBGCC2_HAS_TF_MODE): Remove.
	* config/i386/rtemself.h (IX86_NO_LIBGCC_TFMODE): Define.
	* config/i386/sol2.h (LIBGCC2_HAS_TF_MODE): Remove.
	* config/i386/vx-common.h (IX86_MAYBE_NO_LIBGCC_TFMODE): Define.
	* config/ia64/elf.h (IA64_NO_LIBGCC_TFMODE): Define.
	* config/ia64/freebsd.h (IA64_NO_LIBGCC_TFMODE): Define.
	* config/ia64/hpux.h (LIBGCC2_HAS_XF_MODE, LIBGCC2_HAS_TF_MODE):
	Remove.
	* config/ia64/ia64.c (TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P):
	New macro.
	(ia64_libgcc_floating_mode_supported_p): New function.
	* config/ia64/linux.h (LIBGCC2_HAS_TF_MODE): Remove.
	* config/ia64/vms.h (IA64_NO_LIBGCC_XFMODE)
	(IA64_NO_LIBGCC_TFMODE): Define.
	* config/msp430/msp430.h (LIBGCC2_HAS_DF_MODE): Remove.
	* config/pdp11/pdp11.c (TARGET_SCALAR_MODE_SUPPORTED_P): New
	macro.
	(pdp11_scalar_mode_supported_p): New function.
	* config/rl78/rl78.h (LIBGCC2_HAS_DF_MODE): Remove.
	* config/rx/rx.h (LIBGCC2_HAS_DF_MODE): Remove.


gcc/c-family:
2014-09-11  Joseph Myers  <joseph@codesourcery.com>

	* c-cppbuiltin.c (c_cpp_builtins): Define __LIBGCC_HAS_%s_MODE__
	macros for floating-point modes.

gcc/fortran:
2014-09-11  Joseph Myers  <joseph@codesourcery.com>

	* trans-types.c (gfc_init_kinds): Check
	targetm.libgcc_floating_mode_supported_p for floating-point
	modes.  Check HAVE_TFmode instead of LIBGCC2_HAS_TF_MODE.

libgcc:
2014-09-11  Joseph Myers  <joseph@codesourcery.com>

	* libgcc2.h (LIBGCC2_HAS_SF_MODE): Define using
	__LIBGCC_HAS_SF_MODE__.
	(LIBGCC2_HAS_DF_MODE): Define using __LIBGCC_HAS_DF_MODE__.
	(LIBGCC2_HAS_XF_MODE): Define using __LIBGCC_HAS_XF_MODE__.
	(LIBGCC2_HAS_TF_MODE): Define using __LIBGCC_HAS_TF_MODE__.
	* config/libbid/bid_gcc_intrinsics.h
	(LIBGCC2_LONG_DOUBLE_TYPE_SIZE): Do not define.
	(LIBGCC2_HAS_XF_MODE): Define using __LIBGCC_HAS_XF_MODE__.
	(LIBGCC2_HAS_TF_MODE): Define using __LIBGCC_HAS_TF_MODE__.
	* fixed-bit.h (LIBGCC2_LONG_DOUBLE_TYPE_SIZE): Do not define.
	(LIBGCC2_HAS_SF_MODE): Define using __LIBGCC_HAS_SF_MODE__.
	(LIBGCC2_HAS_DF_MODE): Define using __LIBGCC_HAS_DF_MODE__.

Comments

Richard Biener Sept. 12, 2014, 8:13 a.m. UTC | #1
On Fri, Sep 12, 2014 at 3:22 AM, Joseph S. Myers
<joseph@codesourcery.com> wrote:
> This patch removes the LIBGCC2_HAS_{SF,DF,XF,TF}_MODE target macros,
> replacing them by predefines with -fbuilding-libgcc, together with a
> target hook that can influence those predefines when needed.
>
> The new default is that a floating-point mode is supported in libgcc
> if (a) it passes the scalar_mode_supported_p hook (otherwise it's not
> plausible for it to be supported in libgcc) and (b) it's one of those
> four modes (since those are the modes for which libgcc hardcodes the
> possibility of support).  The target hook can override the default
> choice (in either direction) for modes that pass
> scalar_mode_supported_p (although overriding in the direction of
> returning true when the default would return false only makes sense if
> all relevant functions are specially defined in libgcc for that
> particular target).
>
> The previous default settings depended on various settings such as
> LIBGCC2_LONG_DOUBLE_TYPE_SIZE, as well as targets defining the above
> target macros if the default wasn't correct.
>
> The default scalar_mode_supported_p only declares a floating-point
> mode to be supported if it matches one of float / double / long
> double.  This means that in most cases where a mode is only supported
> conditionally in libgcc (TFmode only supported if it's the mode of
> long double, most commonly), the default gets things right.  Overrides
> were needed in the following cases:
>
> * SFmode would always have been supported in libgcc (the condition was
>   BITS_PER_UNIT == 8, true for all current targets), but pdp11
>   defaults to 64-bit float, and in that case SFmode would fail
>   scalar_mode_supported_p.  I don't know if libgcc actually built for
>   pdp11 (and the port may well no longer be being used), but this
>   patch adds a scalar_mode_supported_p hook to it to ensure SFmode is
>   treated as supported.
>
> * Certain i386 and ia64 targets need the new hook to match the
>   existing cases for when XFmode or TFmode support is present in
>   libgcc.  For i386, the hook can always declare XFmode to be
>   supported - the cases where it's not are the cases where long double
>   is TFmode, in which case XFmode fails scalar_mode_supported_p[*] -
>   but TFmode support needs to be conditional.  (And of the targets not
>   defining LIBGCC2_HAS_TF_MODE before this patch, some defined
>   LONG_DOUBLE_TYPE_SIZE to 64, so ensuring LIBGCC2_HAS_TF_MODE would
>   always be false, while others did not define it, so allowing it to
>   be true in the -mlong-double-128 case.  This patch matches that
>   logic, although I suspect all the latter targets would have been
>   broken if you tried to enable -mlong-double-128 by default, for lack
>   of the soft-fp TFmode support in libgcc, which is separately
>   configured.)
>
>   [*] I don't know if it's deliberate not to support __float80 at all
>   with -mlong-double-128.
>
> In order to implement the default version of the new hook,
> insn-modes.h was made to contain macros such as HAVE_TFmode for each
> machine mode, so the default hook can contain conditionals on whether
> XFmode and TFmode exist (to match the hardcoding of a list of modes in
> libgcc).  This is also used in fortran/trans-types.c; previously it
> had a conditional on defined(LIBGCC2_HAS_TF_MODE) (a bit dubious,
> since it ignored the value of the macro), which is replaced by testing
> defined(HAVE_TFmode), in conjunction with requiring
> targetm.libgcc_floating_mode_supported_p.
>
> (Fortran is testing something stronger than that hook: not only is
> libgcc support required, but also libm or equivalent.  Thus, it has a
> test for ENABLE_LIBQUADMATH_SUPPORT in the case that the mode is
> TFmode and that's not the same as any of the three standard types.
> The old and new tests are intended to accept exactly the same set of
> modes for all targets.)
>
> Apart from the four target macros eliminated by this patch, it gets us
> closer to eliminating LIBGCC2_LONG_DOUBLE_TYPE_SIZE as well, though a
> few more places using that macro need changing first.
>
> Bootstrapped with no regressions on x86_64-unknown-linux-gnu; also
> built cc1 for crosses to ia64-elf and pdp11-none as a minimal test of
> changes for those targets.  OK to commit?

Ok.

Thanks,
Richard.

> gcc:
> 2014-09-11  Joseph Myers  <joseph@codesourcery.com>
>
>         * target.def (libgcc_floating_mode_supported_p): New hook.
>         * targhooks.c (default_libgcc_floating_mode_supported_p): New
>         function.
>         * targhooks.h (default_libgcc_floating_mode_supported_p): Declare.
>         * doc/tm.texi.in (LIBGCC2_HAS_DF_MODE, LIBGCC2_HAS_XF_MODE)
>         (LIBGCC2_HAS_TF_MODE): Remove.
>         (TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P): New @hook.
>         * doc/tm.texi: Regenerate.
>         * genmodes.c (emit_insn_modes_h): Define HAVE_%smode for each
>         machine mode.
>         * system.h (LIBGCC2_HAS_SF_MODE, LIBGCC2_HAS_DF_MODE)
>         (LIBGCC2_HAS_XF_MODE, LIBGCC2_HAS_TF_MODE): Poison.
>         * config/i386/cygming.h (LIBGCC2_HAS_TF_MODE): Remove.
>         * config/i386/darwin.h (LIBGCC2_HAS_TF_MODE): Remove.
>         * config/i386/djgpp.h (IX86_MAYBE_NO_LIBGCC_TFMODE): Define.
>         * config/i386/dragonfly.h (LIBGCC2_HAS_TF_MODE): Remove.
>         * config/i386/freebsd.h (LIBGCC2_HAS_TF_MODE): Remove.
>         * config/i386/gnu-user-common.h (LIBGCC2_HAS_TF_MODE): Remove.
>         * config/i386/i386-interix.h (IX86_NO_LIBGCC_TFMODE): Define.
>         * config/i386/i386.c (ix86_libgcc_floating_mode_supported_p): New
>         function.
>         (TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P): Define.
>         * config/i386/i386elf.h (IX86_MAYBE_NO_LIBGCC_TFMODE): Define.
>         * config/i386/lynx.h (IX86_MAYBE_NO_LIBGCC_TFMODE): Define.
>         * config/i386/netbsd-elf.h (IX86_MAYBE_NO_LIBGCC_TFMODE): Define.
>         * config/i386/netbsd64.h (IX86_MAYBE_NO_LIBGCC_TFMODE): Define.
>         * config/i386/nto.h (IX86_MAYBE_NO_LIBGCC_TFMODE): Define.
>         * config/i386/openbsd.h (IX86_MAYBE_NO_LIBGCC_TFMODE): Define.
>         * config/i386/openbsdelf.h (LIBGCC2_HAS_TF_MODE): Remove.
>         * config/i386/rtemself.h (IX86_NO_LIBGCC_TFMODE): Define.
>         * config/i386/sol2.h (LIBGCC2_HAS_TF_MODE): Remove.
>         * config/i386/vx-common.h (IX86_MAYBE_NO_LIBGCC_TFMODE): Define.
>         * config/ia64/elf.h (IA64_NO_LIBGCC_TFMODE): Define.
>         * config/ia64/freebsd.h (IA64_NO_LIBGCC_TFMODE): Define.
>         * config/ia64/hpux.h (LIBGCC2_HAS_XF_MODE, LIBGCC2_HAS_TF_MODE):
>         Remove.
>         * config/ia64/ia64.c (TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P):
>         New macro.
>         (ia64_libgcc_floating_mode_supported_p): New function.
>         * config/ia64/linux.h (LIBGCC2_HAS_TF_MODE): Remove.
>         * config/ia64/vms.h (IA64_NO_LIBGCC_XFMODE)
>         (IA64_NO_LIBGCC_TFMODE): Define.
>         * config/msp430/msp430.h (LIBGCC2_HAS_DF_MODE): Remove.
>         * config/pdp11/pdp11.c (TARGET_SCALAR_MODE_SUPPORTED_P): New
>         macro.
>         (pdp11_scalar_mode_supported_p): New function.
>         * config/rl78/rl78.h (LIBGCC2_HAS_DF_MODE): Remove.
>         * config/rx/rx.h (LIBGCC2_HAS_DF_MODE): Remove.
>
>
> gcc/c-family:
> 2014-09-11  Joseph Myers  <joseph@codesourcery.com>
>
>         * c-cppbuiltin.c (c_cpp_builtins): Define __LIBGCC_HAS_%s_MODE__
>         macros for floating-point modes.
>
> gcc/fortran:
> 2014-09-11  Joseph Myers  <joseph@codesourcery.com>
>
>         * trans-types.c (gfc_init_kinds): Check
>         targetm.libgcc_floating_mode_supported_p for floating-point
>         modes.  Check HAVE_TFmode instead of LIBGCC2_HAS_TF_MODE.
>
> libgcc:
> 2014-09-11  Joseph Myers  <joseph@codesourcery.com>
>
>         * libgcc2.h (LIBGCC2_HAS_SF_MODE): Define using
>         __LIBGCC_HAS_SF_MODE__.
>         (LIBGCC2_HAS_DF_MODE): Define using __LIBGCC_HAS_DF_MODE__.
>         (LIBGCC2_HAS_XF_MODE): Define using __LIBGCC_HAS_XF_MODE__.
>         (LIBGCC2_HAS_TF_MODE): Define using __LIBGCC_HAS_TF_MODE__.
>         * config/libbid/bid_gcc_intrinsics.h
>         (LIBGCC2_LONG_DOUBLE_TYPE_SIZE): Do not define.
>         (LIBGCC2_HAS_XF_MODE): Define using __LIBGCC_HAS_XF_MODE__.
>         (LIBGCC2_HAS_TF_MODE): Define using __LIBGCC_HAS_TF_MODE__.
>         * fixed-bit.h (LIBGCC2_LONG_DOUBLE_TYPE_SIZE): Do not define.
>         (LIBGCC2_HAS_SF_MODE): Define using __LIBGCC_HAS_SF_MODE__.
>         (LIBGCC2_HAS_DF_MODE): Define using __LIBGCC_HAS_DF_MODE__.
>
> Index: gcc/c-family/c-cppbuiltin.c
> ===================================================================
> --- gcc/c-family/c-cppbuiltin.c (revision 215170)
> +++ gcc/c-family/c-cppbuiltin.c (working copy)
> @@ -956,6 +956,13 @@ c_cpp_builtins (cpp_reader *pfile)
>           sprintf (macro_name, "__LIBGCC_%s_MANT_DIG__", name);
>           builtin_define_with_int_value (macro_name,
>                                          REAL_MODE_FORMAT (mode)->p);
> +         if (!targetm.scalar_mode_supported_p (mode)
> +             || !targetm.libgcc_floating_mode_supported_p (mode))
> +           continue;
> +         macro_name = (char *) alloca (strlen (name)
> +                                       + sizeof ("__LIBGCC_HAS__MODE__"));
> +         sprintf (macro_name, "__LIBGCC_HAS_%s_MODE__", name);
> +         cpp_define (pfile, macro_name);
>         }
>
>        /* For libgcc crtstuff.c and libgcc2.c.  */
> Index: gcc/config/i386/cygming.h
> ===================================================================
> --- gcc/config/i386/cygming.h   (revision 215170)
> +++ gcc/config/i386/cygming.h   (working copy)
> @@ -340,8 +340,6 @@ do {                                                \
>    asm_output_aligned_bss ((FILE), (DECL), (NAME), (SIZE), (ALIGN))
>
>  /* Put all *tf routines in libgcc.  */
> -#undef LIBGCC2_HAS_TF_MODE
> -#define LIBGCC2_HAS_TF_MODE 1
>  #define LIBGCC2_TF_CEXT q
>
>  /* Output function declarations at the end of the file.  */
> Index: gcc/config/i386/darwin.h
> ===================================================================
> --- gcc/config/i386/darwin.h    (revision 215170)
> +++ gcc/config/i386/darwin.h    (working copy)
> @@ -154,8 +154,6 @@ extern int darwin_emit_branch_islands;
>  #define SHIFT_DOUBLE_OMITS_COUNT 0
>
>  /* Put all *tf routines in libgcc.  */
> -#undef LIBGCC2_HAS_TF_MODE
> -#define LIBGCC2_HAS_TF_MODE 1
>  #define LIBGCC2_TF_CEXT q
>
>  #undef TARGET_ASM_FILE_END
> Index: gcc/config/i386/djgpp.h
> ===================================================================
> --- gcc/config/i386/djgpp.h     (revision 215170)
> +++ gcc/config/i386/djgpp.h     (working copy)
> @@ -177,3 +177,5 @@ while (0)
>  /* Support for C++ templates.  */
>  #undef MAKE_DECL_ONE_ONLY
>  #define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1)
> +
> +#define IX86_MAYBE_NO_LIBGCC_TFMODE
> Index: gcc/config/i386/dragonfly.h
> ===================================================================
> --- gcc/config/i386/dragonfly.h (revision 215170)
> +++ gcc/config/i386/dragonfly.h (working copy)
> @@ -90,8 +90,6 @@ see the files COPYING3 and COPYING.RUNTIME respect
>  #define TARGET_96_ROUND_53_LONG_DOUBLE (!TARGET_64BIT)
>
>  /* Put all *tf routines in libgcc.  */
> -#undef LIBGCC2_HAS_TF_MODE
> -#define LIBGCC2_HAS_TF_MODE 1
>  #define LIBGCC2_TF_CEXT q
>
>  /* Static stack checking is supported by means of probes.  */
> Index: gcc/config/i386/freebsd.h
> ===================================================================
> --- gcc/config/i386/freebsd.h   (revision 215170)
> +++ gcc/config/i386/freebsd.h   (working copy)
> @@ -132,8 +132,6 @@ along with GCC; see the file COPYING3.  If not see
>  #define TARGET_96_ROUND_53_LONG_DOUBLE (!TARGET_64BIT)
>
>  /* Put all *tf routines in libgcc.  */
> -#undef LIBGCC2_HAS_TF_MODE
> -#define LIBGCC2_HAS_TF_MODE 1
>  #define LIBGCC2_TF_CEXT q
>
>  /* Static stack checking is supported by means of probes.  */
> Index: gcc/config/i386/gnu-user-common.h
> ===================================================================
> --- gcc/config/i386/gnu-user-common.h   (revision 215170)
> +++ gcc/config/i386/gnu-user-common.h   (working copy)
> @@ -58,8 +58,6 @@ along with GCC; see the file COPYING3.  If not see
>    GNU_USER_TARGET_ENDFILE_SPEC
>
>  /* Put all *tf routines in libgcc.  */
> -#undef LIBGCC2_HAS_TF_MODE
> -#define LIBGCC2_HAS_TF_MODE 1
>  #define LIBGCC2_TF_CEXT q
>
>  #define TARGET_ASM_FILE_END file_end_indicate_exec_stack
> Index: gcc/config/i386/i386-interix.h
> ===================================================================
> --- gcc/config/i386/i386-interix.h      (revision 215170)
> +++ gcc/config/i386/i386-interix.h      (working copy)
> @@ -143,6 +143,8 @@ do {                                                                        \
>  #undef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
>  #define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
>
> +#define IX86_NO_LIBGCC_TFMODE
> +
>  #undef TARGET_LIBC_HAS_FUNCTION
>  #define TARGET_LIBC_HAS_FUNCTION no_c99_libc_has_function
>
> Index: gcc/config/i386/i386.c
> ===================================================================
> --- gcc/config/i386/i386.c      (revision 215170)
> +++ gcc/config/i386/i386.c      (working copy)
> @@ -41217,6 +41217,31 @@ ix86_vector_mode_supported_p (enum machine_mode mo
>    return false;
>  }
>
> +/* Implement target hook libgcc_floating_mode_supported_p.  */
> +static bool
> +ix86_libgcc_floating_mode_supported_p (enum machine_mode mode)
> +{
> +  switch (mode)
> +    {
> +    case SFmode:
> +    case DFmode:
> +    case XFmode:
> +      return true;
> +
> +    case TFmode:
> +#ifdef IX86_NO_LIBGCC_TFMODE
> +      return false;
> +#elif defined IX86_MAYBE_NO_LIBGCC_TFMODE
> +      return TARGET_LONG_DOUBLE_128;
> +#else
> +      return true;
> +#endif
> +
> +    default:
> +      return false;
> +    }
> +}
> +
>  /* Target hook for c_mode_for_suffix.  */
>  static enum machine_mode
>  ix86_c_mode_for_suffix (char suffix)
> @@ -47282,6 +47307,10 @@ ix86_atomic_assign_expand_fenv (tree *hold, tree *
>  #undef TARGET_VECTOR_MODE_SUPPORTED_P
>  #define TARGET_VECTOR_MODE_SUPPORTED_P ix86_vector_mode_supported_p
>
> +#undef TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P
> +#define TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P \
> +  ix86_libgcc_floating_mode_supported_p
> +
>  #undef TARGET_C_MODE_FOR_SUFFIX
>  #define TARGET_C_MODE_FOR_SUFFIX ix86_c_mode_for_suffix
>
> Index: gcc/config/i386/i386elf.h
> ===================================================================
> --- gcc/config/i386/i386elf.h   (revision 215170)
> +++ gcc/config/i386/i386elf.h   (working copy)
> @@ -101,3 +101,5 @@ along with GCC; see the file COPYING3.  If not see
>  #undef ASM_OUTPUT_ALIGNED_BSS
>  #define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
>    asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
> +
> +#define IX86_MAYBE_NO_LIBGCC_TFMODE
> Index: gcc/config/i386/lynx.h
> ===================================================================
> --- gcc/config/i386/lynx.h      (revision 215170)
> +++ gcc/config/i386/lynx.h      (working copy)
> @@ -85,3 +85,5 @@ along with GCC; see the file COPYING3.  If not see
>     TLS is detected by configure.  We undefine it here.  */
>
>  #undef HAVE_AS_TLS
> +
> +#define IX86_MAYBE_NO_LIBGCC_TFMODE
> Index: gcc/config/i386/netbsd-elf.h
> ===================================================================
> --- gcc/config/i386/netbsd-elf.h        (revision 215170)
> +++ gcc/config/i386/netbsd-elf.h        (working copy)
> @@ -119,3 +119,5 @@ along with GCC; see the file COPYING3.  If not see
>  #define DEFAULT_PCC_STRUCT_RETURN 1
>
>  #define HAVE_ENABLE_EXECUTE_STACK
> +
> +#define IX86_MAYBE_NO_LIBGCC_TFMODE
> Index: gcc/config/i386/netbsd64.h
> ===================================================================
> --- gcc/config/i386/netbsd64.h  (revision 215170)
> +++ gcc/config/i386/netbsd64.h  (working copy)
> @@ -67,3 +67,5 @@ along with GCC; see the file COPYING3.  If not see
>  }
>
>  #define HAVE_ENABLE_EXECUTE_STACK
> +
> +#define IX86_MAYBE_NO_LIBGCC_TFMODE
> Index: gcc/config/i386/nto.h
> ===================================================================
> --- gcc/config/i386/nto.h       (revision 215170)
> +++ gcc/config/i386/nto.h       (working copy)
> @@ -103,3 +103,5 @@ crti.o%s \
>  #define TARGET_POSIX_IO
>
>  #undef DBX_REGISTER_NUMBER
> +
> +#define IX86_MAYBE_NO_LIBGCC_TFMODE
> Index: gcc/config/i386/openbsd.h
> ===================================================================
> --- gcc/config/i386/openbsd.h   (revision 215170)
> +++ gcc/config/i386/openbsd.h   (working copy)
> @@ -99,3 +99,5 @@ along with GCC; see the file COPYING3.  If not see
>  #undef ASM_QUAD
>
>  #define TARGET_HAVE_NAMED_SECTIONS false
> +
> +#define IX86_MAYBE_NO_LIBGCC_TFMODE
> Index: gcc/config/i386/openbsdelf.h
> ===================================================================
> --- gcc/config/i386/openbsdelf.h        (revision 215170)
> +++ gcc/config/i386/openbsdelf.h        (working copy)
> @@ -113,6 +113,4 @@ along with GCC; see the file COPYING3.  If not see
>  #define HAVE_ENABLE_EXECUTE_STACK
>
>  /* Put all *tf routines in libgcc.  */
> -#undef LIBGCC2_HAS_TF_MODE
> -#define LIBGCC2_HAS_TF_MODE 1
>  #define LIBGCC2_TF_CEXT q
> Index: gcc/config/i386/rtemself.h
> ===================================================================
> --- gcc/config/i386/rtemself.h  (revision 215170)
> +++ gcc/config/i386/rtemself.h  (working copy)
> @@ -38,3 +38,5 @@ along with GCC; see the file COPYING3.  If not see
>  #else
>  #define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 80
>  #endif
> +
> +#define IX86_NO_LIBGCC_TFMODE
> Index: gcc/config/i386/sol2.h
> ===================================================================
> --- gcc/config/i386/sol2.h      (revision 215170)
> +++ gcc/config/i386/sol2.h      (working copy)
> @@ -238,6 +238,4 @@ along with GCC; see the file COPYING3.  If not see
>  #endif
>
>  /* Put all *tf routines in libgcc.  */
> -#undef LIBGCC2_HAS_TF_MODE
> -#define LIBGCC2_HAS_TF_MODE 1
>  #define LIBGCC2_TF_CEXT q
> Index: gcc/config/i386/vx-common.h
> ===================================================================
> --- gcc/config/i386/vx-common.h (revision 215170)
> +++ gcc/config/i386/vx-common.h (working copy)
> @@ -31,3 +31,5 @@ along with GCC; see the file COPYING3.  If not see
>
>  #undef DBX_REGISTER_NUMBER
>  #define DBX_REGISTER_NUMBER(n)  svr4_dbx_register_map[n]
> +
> +#define IX86_MAYBE_NO_LIBGCC_TFMODE
> Index: gcc/config/ia64/elf.h
> ===================================================================
> --- gcc/config/ia64/elf.h       (revision 215170)
> +++ gcc/config/ia64/elf.h       (working copy)
> @@ -65,4 +65,6 @@ see the files COPYING3 and COPYING.RUNTIME respect
>                           %{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}}\
>                         crti.o%s crtbegin.o%s"
>
> +#define IA64_NO_LIBGCC_TFMODE
> +
>  /* End of elf.h */
> Index: gcc/config/ia64/freebsd.h
> ===================================================================
> --- gcc/config/ia64/freebsd.h   (revision 215170)
> +++ gcc/config/ia64/freebsd.h   (working copy)
> @@ -50,3 +50,5 @@ along with GCC; see the file COPYING3.  If not see
>  #define TARGET_ELF             1
>
>  #define JMP_BUF_SIZE  76
> +
> +#define IA64_NO_LIBGCC_TFMODE
> Index: gcc/config/ia64/hpux.h
> ===================================================================
> --- gcc/config/ia64/hpux.h      (revision 215170)
> +++ gcc/config/ia64/hpux.h      (working copy)
> @@ -189,14 +189,6 @@ do {                                                               \
>
>  #define FLOAT_LIB_COMPARE_RETURNS_BOOL(MODE, COMPARISON) ((MODE) == TFmode)
>
> -/* Put all *xf routines in libgcc, regardless of long double size.  */
> -#undef LIBGCC2_HAS_XF_MODE
> -#define LIBGCC2_HAS_XF_MODE 1
> -
> -/* Put all *tf routines in libgcc, regardless of long double size.  */
> -#undef LIBGCC2_HAS_TF_MODE
> -#define LIBGCC2_HAS_TF_MODE 1
> -
>  /* HP-UX headers are C++-compatible.  */
>  #define NO_IMPLICIT_EXTERN_C
>
> Index: gcc/config/ia64/ia64.c
> ===================================================================
> --- gcc/config/ia64/ia64.c      (revision 215170)
> +++ gcc/config/ia64/ia64.c      (working copy)
> @@ -319,6 +319,7 @@ static rtx ia64_struct_value_rtx (tree, int);
>  static tree ia64_gimplify_va_arg (tree, tree, gimple_seq *, gimple_seq *);
>  static bool ia64_scalar_mode_supported_p (enum machine_mode mode);
>  static bool ia64_vector_mode_supported_p (enum machine_mode mode);
> +static bool ia64_libgcc_floating_mode_supported_p (enum machine_mode mode);
>  static bool ia64_legitimate_constant_p (enum machine_mode, rtx);
>  static bool ia64_legitimate_address_p (enum machine_mode, rtx, bool);
>  static bool ia64_cannot_force_const_mem (enum machine_mode, rtx);
> @@ -598,6 +599,10 @@ static const struct attribute_spec ia64_attribute_
>  #undef TARGET_VECTOR_MODE_SUPPORTED_P
>  #define TARGET_VECTOR_MODE_SUPPORTED_P ia64_vector_mode_supported_p
>
> +#undef TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P
> +#define TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P \
> +  ia64_libgcc_floating_mode_supported_p
> +
>  /* ia64 architecture manual 4.4.7: ... reads, writes, and flushes may occur
>     in an order different from the specified program order.  */
>  #undef TARGET_RELAXED_ORDERING
> @@ -10939,6 +10944,36 @@ ia64_vector_mode_supported_p (enum machine_mode mo
>      }
>  }
>
> +/* Implement TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P.  */
> +
> +static bool
> +ia64_libgcc_floating_mode_supported_p (enum machine_mode mode)
> +{
> +  switch (mode)
> +    {
> +    case SFmode:
> +    case DFmode:
> +      return true;
> +
> +    case XFmode:
> +#ifdef IA64_NO_LIBGCC_XFMODE
> +      return false;
> +#else
> +      return true;
> +#endif
> +
> +    case TFmode:
> +#ifdef IA64_NO_LIBGCC_TFMODE
> +      return false;
> +#else
> +      return true;
> +#endif
> +
> +    default:
> +      return false;
> +    }
> +}
> +
>  /* Implement the FUNCTION_PROFILER macro.  */
>
>  void
> Index: gcc/config/ia64/linux.h
> ===================================================================
> --- gcc/config/ia64/linux.h     (revision 215170)
> +++ gcc/config/ia64/linux.h     (working copy)
> @@ -77,8 +77,6 @@ do {                                          \
>  #define LINK_EH_SPEC ""
>
>  /* 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
>
> Index: gcc/config/ia64/vms.h
> ===================================================================
> --- gcc/config/ia64/vms.h       (revision 215170)
> +++ gcc/config/ia64/vms.h       (working copy)
> @@ -154,3 +154,6 @@ STATIC func_ptr __CTOR_LIST__[1]
>  /* Default values for _CRTL_VER and _VMS_VER.  */
>  #define VMS_DEFAULT_CRTL_VER 80300000
>  #define VMS_DEFAULT_VMS_VER 80300000
> +
> +#define IA64_NO_LIBGCC_XFMODE
> +#define IA64_NO_LIBGCC_TFMODE
> Index: gcc/config/msp430/msp430.h
> ===================================================================
> --- gcc/config/msp430/msp430.h  (revision 215170)
> +++ gcc/config/msp430/msp430.h  (working copy)
> @@ -112,7 +112,6 @@ extern bool msp430x;
>  #define DOUBLE_TYPE_SIZE               64
>  #define LONG_DOUBLE_TYPE_SIZE          64 /*DOUBLE_TYPE_SIZE*/
>
> -#define LIBGCC2_HAS_DF_MODE            1
>  #define LIBGCC2_LONG_DOUBLE_TYPE_SIZE   64
>
>  #define DEFAULT_SIGNED_CHAR            0
> Index: gcc/config/pdp11/pdp11.c
> ===================================================================
> --- gcc/config/pdp11/pdp11.c    (revision 215170)
> +++ gcc/config/pdp11/pdp11.c    (working copy)
> @@ -157,6 +157,8 @@ static void pdp11_function_arg_advance (cumulative
>                                         enum machine_mode, const_tree, bool);
>  static void pdp11_conditional_register_usage (void);
>  static bool pdp11_legitimate_constant_p (enum machine_mode, rtx);
> +
> +static bool pdp11_scalar_mode_supported_p (enum machine_mode);
>
>  /* Initialize the GCC target structure.  */
>  #undef TARGET_ASM_BYTE_OP
> @@ -223,6 +225,9 @@ static bool pdp11_legitimate_constant_p (enum mach
>
>  #undef  TARGET_LEGITIMATE_CONSTANT_P
>  #define TARGET_LEGITIMATE_CONSTANT_P pdp11_legitimate_constant_p
> +
> +#undef  TARGET_SCALAR_MODE_SUPPORTED_P
> +#define TARGET_SCALAR_MODE_SUPPORTED_P pdp11_scalar_mode_supported_p
>
>  /* A helper function to determine if REGNO should be saved in the
>     current function's stack frame.  */
> @@ -1901,4 +1906,15 @@ pdp11_legitimate_constant_p (enum machine_mode mod
>    return GET_CODE (x) != CONST_DOUBLE || legitimate_const_double_p (x);
>  }
>
> +/* Implement TARGET_SCALAR_MODE_SUPPORTED_P.  */
> +
> +static bool
> +pdp11_scalar_mode_supported_p (enum machine_mode mode)
> +{
> +  /* Support SFmode even with -mfloat64.  */
> +  if (mode == SFmode)
> +    return true;
> +  return default_scalar_mode_supported_p (mode);
> +}
> +
>  struct gcc_target targetm = TARGET_INITIALIZER;
> Index: gcc/config/rl78/rl78.h
> ===================================================================
> --- gcc/config/rl78/rl78.h      (revision 215170)
> +++ gcc/config/rl78/rl78.h      (working copy)
> @@ -98,7 +98,6 @@
>  #define DOUBLE_TYPE_SIZE               32 /*64*/
>  #define LONG_DOUBLE_TYPE_SIZE          64 /*DOUBLE_TYPE_SIZE*/
>
> -#define LIBGCC2_HAS_DF_MODE            1
>  #define LIBGCC2_LONG_DOUBLE_TYPE_SIZE   64
>
>  #define DEFAULT_SIGNED_CHAR            0
> Index: gcc/config/rx/rx.h
> ===================================================================
> --- gcc/config/rx/rx.h  (revision 215170)
> +++ gcc/config/rx/rx.h  (working copy)
> @@ -131,10 +131,8 @@
>  #define LONG_DOUBLE_TYPE_SIZE          DOUBLE_TYPE_SIZE
>
>  #ifdef __RX_32BIT_DOUBLES__
> -#define LIBGCC2_HAS_DF_MODE            0
>  #define LIBGCC2_LONG_DOUBLE_TYPE_SIZE   32
>  #else
> -#define LIBGCC2_HAS_DF_MODE            1
>  #define LIBGCC2_LONG_DOUBLE_TYPE_SIZE   64
>  #endif
>
> Index: gcc/doc/tm.texi
> ===================================================================
> --- gcc/doc/tm.texi     (revision 215170)
> +++ gcc/doc/tm.texi     (working copy)
> @@ -1549,29 +1549,6 @@ if you want routines in @file{libgcc2.a} for a siz
>  default is @code{LONG_DOUBLE_TYPE_SIZE}.
>  @end defmac
>
> -@defmac LIBGCC2_HAS_DF_MODE
> -Define this macro if neither @code{DOUBLE_TYPE_SIZE} nor
> -@code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE} is
> -@code{DFmode} but you want @code{DFmode} routines in @file{libgcc2.a}
> -anyway.  If you don't define this and either @code{DOUBLE_TYPE_SIZE}
> -or @code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE} is 64 then the default is 1,
> -otherwise it is 0.
> -@end defmac
> -
> -@defmac LIBGCC2_HAS_XF_MODE
> -Define this macro if @code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE} is not
> -@code{XFmode} but you want @code{XFmode} routines in @file{libgcc2.a}
> -anyway.  If you don't define this and @code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE}
> -is 80 then the default is 1, otherwise it is 0.
> -@end defmac
> -
> -@defmac LIBGCC2_HAS_TF_MODE
> -Define this macro if @code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE} is not
> -@code{TFmode} but you want @code{TFmode} routines in @file{libgcc2.a}
> -anyway.  If you don't define this and @code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE}
> -is 128 then the default is 1, otherwise it is 0.
> -@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
> @@ -4226,6 +4203,14 @@ If this hook allows @code{val} to have a scalar mo
>  @code{int8x8x3_t}s in registers rather than forcing them onto the stack.
>  @end deftypefn
>
> +@deftypefn {Target Hook} bool TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P (enum machine_mode @var{mode})
> +Define this to return nonzero if libgcc provides support for the
> +floating-point mode @var{mode}, which is known to pass
> +@code{TARGET_SCALAR_MODE_SUPPORTED_P}.  The default version of this
> +hook returns true for all of @code{SFmode}, @code{DFmode},
> +@code{XFmode} and @code{TFmode}, if such modes exist.
> +@end deftypefn
> +
>  @deftypefn {Target Hook} bool TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P (enum machine_mode @var{mode})
>  Define this to return nonzero for machine modes for which the port has
>  small register classes.  If this target hook returns nonzero for a given
> Index: gcc/doc/tm.texi.in
> ===================================================================
> --- gcc/doc/tm.texi.in  (revision 215170)
> +++ gcc/doc/tm.texi.in  (working copy)
> @@ -1391,29 +1391,6 @@ if you want routines in @file{libgcc2.a} for a siz
>  default is @code{LONG_DOUBLE_TYPE_SIZE}.
>  @end defmac
>
> -@defmac LIBGCC2_HAS_DF_MODE
> -Define this macro if neither @code{DOUBLE_TYPE_SIZE} nor
> -@code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE} is
> -@code{DFmode} but you want @code{DFmode} routines in @file{libgcc2.a}
> -anyway.  If you don't define this and either @code{DOUBLE_TYPE_SIZE}
> -or @code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE} is 64 then the default is 1,
> -otherwise it is 0.
> -@end defmac
> -
> -@defmac LIBGCC2_HAS_XF_MODE
> -Define this macro if @code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE} is not
> -@code{XFmode} but you want @code{XFmode} routines in @file{libgcc2.a}
> -anyway.  If you don't define this and @code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE}
> -is 80 then the default is 1, otherwise it is 0.
> -@end defmac
> -
> -@defmac LIBGCC2_HAS_TF_MODE
> -Define this macro if @code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE} is not
> -@code{TFmode} but you want @code{TFmode} routines in @file{libgcc2.a}
> -anyway.  If you don't define this and @code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE}
> -is 128 then the default is 1, otherwise it is 0.
> -@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
> @@ -3530,6 +3507,8 @@ stack.
>
>  @hook TARGET_ARRAY_MODE_SUPPORTED_P
>
> +@hook TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P
> +
>  @hook TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P
>
>  @hook TARGET_FLAGS_REGNUM
> Index: gcc/fortran/trans-types.c
> ===================================================================
> --- gcc/fortran/trans-types.c   (revision 215170)
> +++ gcc/fortran/trans-types.c   (working copy)
> @@ -31,8 +31,8 @@ along with GCC; see the file COPYING3.  If not see
>                            BOOL_TYPE_SIZE, BITS_PER_UNIT, POINTER_SIZE,
>                            INT_TYPE_SIZE, CHAR_TYPE_SIZE, SHORT_TYPE_SIZE,
>                            LONG_TYPE_SIZE, LONG_LONG_TYPE_SIZE,
> -                          FLOAT_TYPE_SIZE, DOUBLE_TYPE_SIZE,
> -                          LONG_DOUBLE_TYPE_SIZE and LIBGCC2_HAS_TF_MODE.  */
> +                          FLOAT_TYPE_SIZE, DOUBLE_TYPE_SIZE and
> +                          LONG_DOUBLE_TYPE_SIZE.  */
>  #include "tree.h"
>  #include "stor-layout.h"
>  #include "stringpool.h"
> @@ -427,10 +427,13 @@ gfc_init_kinds (void)
>        /* Only let float, double, long double and __float128 go through.
>          Runtime support for others is not provided, so they would be
>          useless.  */
> +       if (!targetm.libgcc_floating_mode_supported_p ((enum machine_mode)
> +                                                      mode))
> +         continue;
>         if (mode != TYPE_MODE (float_type_node)
>             && (mode != TYPE_MODE (double_type_node))
>             && (mode != TYPE_MODE (long_double_type_node))
> -#if defined(LIBGCC2_HAS_TF_MODE) && defined(ENABLE_LIBQUADMATH_SUPPORT)
> +#if defined(HAVE_TFmode) && defined(ENABLE_LIBQUADMATH_SUPPORT)
>             && (mode != TFmode)
>  #endif
>            )
> Index: gcc/genmodes.c
> ===================================================================
> --- gcc/genmodes.c      (revision 215170)
> +++ gcc/genmodes.c      (working copy)
> @@ -1029,6 +1029,7 @@ enum machine_mode\n{");
>         int count_ = printf ("  %smode,", m->name);
>         printf ("%*s/* %s:%d */\n", 27 - count_, "",
>                  trim_filename (m->file), m->line);
> +       printf ("#define HAVE_%smode\n", m->name);
>        }
>
>    puts ("  MAX_MACHINE_MODE,\n");
> Index: gcc/system.h
> ===================================================================
> --- gcc/system.h        (revision 215170)
> +++ gcc/system.h        (working copy)
> @@ -846,7 +846,8 @@ extern void fancy_abort (const char *, int, const
>         CAN_DEBUG_WITHOUT_FP UNLIKELY_EXECUTED_TEXT_SECTION_NAME        \
>         HOT_TEXT_SECTION_NAME LEGITIMATE_CONSTANT_P ALWAYS_STRIP_DOTDOT \
>         OUTPUT_ADDR_CONST_EXTRA SMALL_REGISTER_CLASSES ASM_OUTPUT_IDENT \
> -       ASM_BYTE_OP MEMBER_TYPE_FORCES_BLK
> +       ASM_BYTE_OP MEMBER_TYPE_FORCES_BLK LIBGCC2_HAS_SF_MODE          \
> +       LIBGCC2_HAS_DF_MODE LIBGCC2_HAS_XF_MODE LIBGCC2_HAS_TF_MODE
>
>  /* Target macros only used for code built for the target, that have
>     moved to libgcc-tm.h or have never been present elsewhere.  */
> Index: gcc/target.def
> ===================================================================
> --- gcc/target.def      (revision 215170)
> +++ gcc/target.def      (working copy)
> @@ -2985,6 +2985,16 @@ If this hook allows @code{val} to have a scalar mo
>   bool, (enum machine_mode mode, unsigned HOST_WIDE_INT nelems),
>   hook_bool_mode_uhwi_false)
>
> +DEFHOOK
> +(libgcc_floating_mode_supported_p,
> + "Define this to return nonzero if libgcc provides support for the \n\
> +floating-point mode @var{mode}, which is known to pass \n\
> +@code{TARGET_SCALAR_MODE_SUPPORTED_P}.  The default version of this \n\
> +hook returns true for all of @code{SFmode}, @code{DFmode}, \n\
> +@code{XFmode} and @code{TFmode}, if such modes exist.",
> + bool, (enum machine_mode mode),
> + default_libgcc_floating_mode_supported_p)
> +
>  /* Compute cost of moving data from a register of class FROM to one of
>     TO, using MODE.  */
>  DEFHOOK
> Index: gcc/targhooks.c
> ===================================================================
> --- gcc/targhooks.c     (revision 215170)
> +++ gcc/targhooks.c     (working copy)
> @@ -424,6 +424,33 @@ default_scalar_mode_supported_p (enum machine_mode
>      }
>  }
>
> +/* Return true if libgcc supports floating-point mode MODE (known to
> +   be supported as a scalar mode).  */
> +
> +bool
> +default_libgcc_floating_mode_supported_p (enum machine_mode mode)
> +{
> +  switch (mode)
> +    {
> +#ifdef HAVE_SFmode
> +    case SFmode:
> +#endif
> +#ifdef HAVE_DFmode
> +    case DFmode:
> +#endif
> +#ifdef HAVE_XFmode
> +    case XFmode:
> +#endif
> +#ifdef HAVE_TFmode
> +    case TFmode:
> +#endif
> +      return true;
> +
> +    default:
> +      return false;
> +    }
> +}
> +
>  /* Make some target macros useable by target-independent code.  */
>  bool
>  targhook_words_big_endian (void)
> Index: gcc/targhooks.h
> ===================================================================
> --- gcc/targhooks.h     (revision 215170)
> +++ gcc/targhooks.h     (working copy)
> @@ -67,6 +67,7 @@ extern bool default_print_operand_punct_valid_p (u
>  extern tree default_mangle_assembler_name (const char *);
>
>  extern bool default_scalar_mode_supported_p (enum machine_mode);
> +extern bool default_libgcc_floating_mode_supported_p (enum machine_mode);
>  extern bool targhook_words_big_endian (void);
>  extern bool targhook_float_words_big_endian (void);
>  extern bool default_float_exceptions_rounding_supported_p (void);
> Index: libgcc/config/libbid/bid_gcc_intrinsics.h
> ===================================================================
> --- libgcc/config/libbid/bid_gcc_intrinsics.h   (revision 215170)
> +++ libgcc/config/libbid/bid_gcc_intrinsics.h   (working copy)
> @@ -31,20 +31,18 @@ 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
> +#ifdef __LIBGCC_HAS_XF_MODE__
> +#define LIBGCC2_HAS_XF_MODE 1
> +#else
> +#define LIBGCC2_HAS_XF_MODE 0
>  #endif
>
> -#ifndef LIBGCC2_HAS_XF_MODE
> -#define LIBGCC2_HAS_XF_MODE \
> -  (BITS_PER_UNIT == 8 && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80)
> +#ifdef __LIBGCC_HAS_TF_MODE__
> +#define LIBGCC2_HAS_TF_MODE 1
> +#else
> +#define LIBGCC2_HAS_TF_MODE 0
>  #endif
>
> -#ifndef LIBGCC2_HAS_TF_MODE
> -#define LIBGCC2_HAS_TF_MODE \
> -  (BITS_PER_UNIT == 8 && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
> -#endif
> -
>  #ifndef BID_HAS_XF_MODE
>  #define BID_HAS_XF_MODE LIBGCC2_HAS_XF_MODE
>  #endif
> Index: libgcc/fixed-bit.h
> ===================================================================
> --- libgcc/fixed-bit.h  (revision 215170)
> +++ libgcc/fixed-bit.h  (working copy)
> @@ -45,21 +45,18 @@ see the files COPYING3 and COPYING.RUNTIME respect
>     Ex: If we define FROM_QQ and TO_SI, the conversion from QQ to SI is
>     generated.  */
>
> -#ifndef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
> -#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
> +#ifdef __LIBGCC_HAS_SF_MODE__
> +#define LIBGCC2_HAS_SF_MODE 1
> +#else
> +#define LIBGCC2_HAS_SF_MODE 0
>  #endif
>
> -#ifndef LIBGCC2_HAS_SF_MODE
> -#define LIBGCC2_HAS_SF_MODE (BITS_PER_UNIT == 8)
> +#ifdef __LIBGCC_HAS_DF_MODE__
> +#define LIBGCC2_HAS_DF_MODE 1
> +#else
> +#define LIBGCC2_HAS_DF_MODE 0
>  #endif
>
> -#ifndef LIBGCC2_HAS_DF_MODE
> -#define LIBGCC2_HAS_DF_MODE \
> -  (BITS_PER_UNIT == 8 \
> -   && (__SIZEOF_DOUBLE__ * __CHAR_BIT__ == 64 \
> -       || LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64))
> -#endif
> -
>  typedef          int QItype     __attribute__ ((mode (QI)));
>  typedef unsigned int UQItype    __attribute__ ((mode (QI)));
>  typedef          int HItype     __attribute__ ((mode (HI)));
> Index: libgcc/libgcc2.h
> ===================================================================
> --- libgcc/libgcc2.h    (revision 215170)
> +++ libgcc/libgcc2.h    (working copy)
> @@ -38,25 +38,28 @@ extern void __eprintf (const char *, const char *,
>  #define LIBGCC2_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
>  #endif
>
> -#ifndef LIBGCC2_HAS_SF_MODE
> -#define LIBGCC2_HAS_SF_MODE (BITS_PER_UNIT == 8)
> +#ifdef __LIBGCC_HAS_SF_MODE__
> +#define LIBGCC2_HAS_SF_MODE 1
> +#else
> +#define LIBGCC2_HAS_SF_MODE 0
>  #endif
>
> -#ifndef LIBGCC2_HAS_DF_MODE
> -#define LIBGCC2_HAS_DF_MODE \
> -  (BITS_PER_UNIT == 8 \
> -   && (__SIZEOF_DOUBLE__ * __CHAR_BIT__ == 64 \
> -       || LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64))
> +#ifdef __LIBGCC_HAS_DF_MODE__
> +#define LIBGCC2_HAS_DF_MODE 1
> +#else
> +#define LIBGCC2_HAS_DF_MODE 0
>  #endif
>
> -#ifndef LIBGCC2_HAS_XF_MODE
> -#define LIBGCC2_HAS_XF_MODE \
> -  (BITS_PER_UNIT == 8 && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80)
> +#ifdef __LIBGCC_HAS_XF_MODE__
> +#define LIBGCC2_HAS_XF_MODE 1
> +#else
> +#define LIBGCC2_HAS_XF_MODE 0
>  #endif
>
> -#ifndef LIBGCC2_HAS_TF_MODE
> -#define LIBGCC2_HAS_TF_MODE \
> -  (BITS_PER_UNIT == 8 && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
> +#ifdef __LIBGCC_HAS_TF_MODE__
> +#define LIBGCC2_HAS_TF_MODE 1
> +#else
> +#define LIBGCC2_HAS_TF_MODE 0
>  #endif
>
>  #ifndef __LIBGCC_SF_MANT_DIG__
>
> --
> Joseph S. Myers
> joseph@codesourcery.com
Paul Koning Sept. 12, 2014, 5:30 p.m. UTC | #2
On Sep 11, 2014, at 9:22 PM, Joseph S. Myers <joseph@codesourcery.com> wrote:

> This patch removes the LIBGCC2_HAS_{SF,DF,XF,TF}_MODE target macros,
> replacing them by predefines with -fbuilding-libgcc, together with a
> target hook that can influence those predefines when needed.
> 
> The new default is that a floating-point mode is supported in libgcc
> if (a) it passes the scalar_mode_supported_p hook (otherwise it's not
> plausible for it to be supported in libgcc) and (b) it's one of those
> four modes (since those are the modes for which libgcc hardcodes the
> possibility of support).  The target hook can override the default
> choice (in either direction) for modes that pass
> scalar_mode_supported_p (although overriding in the direction of
> returning true when the default would return false only makes sense if
> all relevant functions are specially defined in libgcc for that
> particular target).
> 
> The previous default settings depended on various settings such as
> LIBGCC2_LONG_DOUBLE_TYPE_SIZE, as well as targets defining the above
> target macros if the default wasn't correct.
> 
> The default scalar_mode_supported_p only declares a floating-point
> mode to be supported if it matches one of float / double / long
> double.  This means that in most cases where a mode is only supported
> conditionally in libgcc (TFmode only supported if it's the mode of
> long double, most commonly), the default gets things right.  Overrides
> were needed in the following cases:
> 
> * SFmode would always have been supported in libgcc (the condition was
>  BITS_PER_UNIT == 8, true for all current targets), but pdp11
>  defaults to 64-bit float, and in that case SFmode would fail
>  scalar_mode_supported_p.  I don't know if libgcc actually built for
>  pdp11 (and the port may well no longer be being used), but this
>  patch adds a scalar_mode_supported_p hook to it to ensure SFmode is
>  treated as supported.

I thought it does build.  I continue to work to keep that port alive.

The change looks fine.

The ideal solution, I think, would be to handle the choice of float length that the pdp11 target has via the multilib machinery.  Currently it does not do that.  If multilib were added for that at some point, would that require a change of the code in that hook?

	paul
Joseph Myers Sept. 12, 2014, 9:31 p.m. UTC | #3
On Fri, 12 Sep 2014, Paul_Koning@Dell.com wrote:

> > * SFmode would always have been supported in libgcc (the condition was
> >  BITS_PER_UNIT == 8, true for all current targets), but pdp11
> >  defaults to 64-bit float, and in that case SFmode would fail
> >  scalar_mode_supported_p.  I don't know if libgcc actually built for
> >  pdp11 (and the port may well no longer be being used), but this
> >  patch adds a scalar_mode_supported_p hook to it to ensure SFmode is
> >  treated as supported.
> 
> I thought it does build.  I continue to work to keep that port alive.
> 
> The change looks fine.
> 
> The ideal solution, I think, would be to handle the choice of float 
> length that the pdp11 target has via the multilib machinery.  Currently 
> it does not do that.  If multilib were added for that at some point, 
> would that require a change of the code in that hook?

I think the ideal is for the back end to accept a mode in 
scalar_mode_supported_p if it can generate something sensible (either 
inline code or calls to libgcc functions) for arithmetic on that mode, 
rather than ICEs or otherwise invalid code, even if the libgcc functions 
don't actually exist.  (Thus, ix86_scalar_mode_supported_p always 
considers TFmode to be supported, whether or not the libgcc support is 
present.)

On that basis, my hook to treat SFmode as always supported for pdp11 (so 
it can be accessed with __attribute__((mode(SF))), whether or not it's 
also float) seems to be the right thing.

(Various back ends would, if they adopted my ideal, then also need to add 
the libgcc_floating_mode_supported_p hook to indicate the conditional lack 
of libgcc support for certain modes.  E.g. for several back ends, TFmode 
is only supported in libgcc if it's long double, and most of the runtime 
support is expected to be in libc not libgcc, under symbol names from some 
ABI for that architecture.  In those cases, building in the libgcc support 
for e.g. __multc3 in the absence of libc support would be problematic, 
because it would reference undefined libc functions.)
diff mbox

Patch

Index: gcc/c-family/c-cppbuiltin.c
===================================================================
--- gcc/c-family/c-cppbuiltin.c	(revision 215170)
+++ gcc/c-family/c-cppbuiltin.c	(working copy)
@@ -956,6 +956,13 @@  c_cpp_builtins (cpp_reader *pfile)
 	  sprintf (macro_name, "__LIBGCC_%s_MANT_DIG__", name);
 	  builtin_define_with_int_value (macro_name,
 					 REAL_MODE_FORMAT (mode)->p);
+	  if (!targetm.scalar_mode_supported_p (mode)
+	      || !targetm.libgcc_floating_mode_supported_p (mode))
+	    continue;
+	  macro_name = (char *) alloca (strlen (name)
+					+ sizeof ("__LIBGCC_HAS__MODE__"));
+	  sprintf (macro_name, "__LIBGCC_HAS_%s_MODE__", name);
+	  cpp_define (pfile, macro_name);
 	}
 
       /* For libgcc crtstuff.c and libgcc2.c.  */
Index: gcc/config/i386/cygming.h
===================================================================
--- gcc/config/i386/cygming.h	(revision 215170)
+++ gcc/config/i386/cygming.h	(working copy)
@@ -340,8 +340,6 @@  do {						\
   asm_output_aligned_bss ((FILE), (DECL), (NAME), (SIZE), (ALIGN))
 
 /* Put all *tf routines in libgcc.  */
-#undef LIBGCC2_HAS_TF_MODE
-#define LIBGCC2_HAS_TF_MODE 1
 #define LIBGCC2_TF_CEXT q
 
 /* Output function declarations at the end of the file.  */
Index: gcc/config/i386/darwin.h
===================================================================
--- gcc/config/i386/darwin.h	(revision 215170)
+++ gcc/config/i386/darwin.h	(working copy)
@@ -154,8 +154,6 @@  extern int darwin_emit_branch_islands;
 #define SHIFT_DOUBLE_OMITS_COUNT 0
 
 /* Put all *tf routines in libgcc.  */
-#undef LIBGCC2_HAS_TF_MODE
-#define LIBGCC2_HAS_TF_MODE 1
 #define LIBGCC2_TF_CEXT q
 
 #undef TARGET_ASM_FILE_END
Index: gcc/config/i386/djgpp.h
===================================================================
--- gcc/config/i386/djgpp.h	(revision 215170)
+++ gcc/config/i386/djgpp.h	(working copy)
@@ -177,3 +177,5 @@  while (0)
 /* Support for C++ templates.  */
 #undef MAKE_DECL_ONE_ONLY
 #define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1)
+
+#define IX86_MAYBE_NO_LIBGCC_TFMODE
Index: gcc/config/i386/dragonfly.h
===================================================================
--- gcc/config/i386/dragonfly.h	(revision 215170)
+++ gcc/config/i386/dragonfly.h	(working copy)
@@ -90,8 +90,6 @@  see the files COPYING3 and COPYING.RUNTIME respect
 #define TARGET_96_ROUND_53_LONG_DOUBLE (!TARGET_64BIT)
 
 /* Put all *tf routines in libgcc.  */
-#undef LIBGCC2_HAS_TF_MODE
-#define LIBGCC2_HAS_TF_MODE 1
 #define LIBGCC2_TF_CEXT q
 
 /* Static stack checking is supported by means of probes.  */
Index: gcc/config/i386/freebsd.h
===================================================================
--- gcc/config/i386/freebsd.h	(revision 215170)
+++ gcc/config/i386/freebsd.h	(working copy)
@@ -132,8 +132,6 @@  along with GCC; see the file COPYING3.  If not see
 #define TARGET_96_ROUND_53_LONG_DOUBLE (!TARGET_64BIT)
 
 /* Put all *tf routines in libgcc.  */
-#undef LIBGCC2_HAS_TF_MODE
-#define LIBGCC2_HAS_TF_MODE 1
 #define LIBGCC2_TF_CEXT q
 
 /* Static stack checking is supported by means of probes.  */
Index: gcc/config/i386/gnu-user-common.h
===================================================================
--- gcc/config/i386/gnu-user-common.h	(revision 215170)
+++ gcc/config/i386/gnu-user-common.h	(working copy)
@@ -58,8 +58,6 @@  along with GCC; see the file COPYING3.  If not see
   GNU_USER_TARGET_ENDFILE_SPEC
 
 /* Put all *tf routines in libgcc.  */
-#undef LIBGCC2_HAS_TF_MODE
-#define LIBGCC2_HAS_TF_MODE 1
 #define LIBGCC2_TF_CEXT q
 
 #define TARGET_ASM_FILE_END file_end_indicate_exec_stack
Index: gcc/config/i386/i386-interix.h
===================================================================
--- gcc/config/i386/i386-interix.h	(revision 215170)
+++ gcc/config/i386/i386-interix.h	(working copy)
@@ -143,6 +143,8 @@  do {									\
 #undef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
 #define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
 
+#define IX86_NO_LIBGCC_TFMODE
+
 #undef TARGET_LIBC_HAS_FUNCTION
 #define TARGET_LIBC_HAS_FUNCTION no_c99_libc_has_function
 
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(revision 215170)
+++ gcc/config/i386/i386.c	(working copy)
@@ -41217,6 +41217,31 @@  ix86_vector_mode_supported_p (enum machine_mode mo
   return false;
 }
 
+/* Implement target hook libgcc_floating_mode_supported_p.  */
+static bool
+ix86_libgcc_floating_mode_supported_p (enum machine_mode mode)
+{
+  switch (mode)
+    {
+    case SFmode:
+    case DFmode:
+    case XFmode:
+      return true;
+
+    case TFmode:
+#ifdef IX86_NO_LIBGCC_TFMODE
+      return false;
+#elif defined IX86_MAYBE_NO_LIBGCC_TFMODE
+      return TARGET_LONG_DOUBLE_128;
+#else
+      return true;
+#endif
+
+    default:
+      return false;
+    }
+}
+
 /* Target hook for c_mode_for_suffix.  */
 static enum machine_mode
 ix86_c_mode_for_suffix (char suffix)
@@ -47282,6 +47307,10 @@  ix86_atomic_assign_expand_fenv (tree *hold, tree *
 #undef TARGET_VECTOR_MODE_SUPPORTED_P
 #define TARGET_VECTOR_MODE_SUPPORTED_P ix86_vector_mode_supported_p
 
+#undef TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P
+#define TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P \
+  ix86_libgcc_floating_mode_supported_p
+
 #undef TARGET_C_MODE_FOR_SUFFIX
 #define TARGET_C_MODE_FOR_SUFFIX ix86_c_mode_for_suffix
 
Index: gcc/config/i386/i386elf.h
===================================================================
--- gcc/config/i386/i386elf.h	(revision 215170)
+++ gcc/config/i386/i386elf.h	(working copy)
@@ -101,3 +101,5 @@  along with GCC; see the file COPYING3.  If not see
 #undef ASM_OUTPUT_ALIGNED_BSS
 #define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
   asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
+
+#define IX86_MAYBE_NO_LIBGCC_TFMODE
Index: gcc/config/i386/lynx.h
===================================================================
--- gcc/config/i386/lynx.h	(revision 215170)
+++ gcc/config/i386/lynx.h	(working copy)
@@ -85,3 +85,5 @@  along with GCC; see the file COPYING3.  If not see
    TLS is detected by configure.  We undefine it here.  */
 
 #undef HAVE_AS_TLS
+
+#define IX86_MAYBE_NO_LIBGCC_TFMODE
Index: gcc/config/i386/netbsd-elf.h
===================================================================
--- gcc/config/i386/netbsd-elf.h	(revision 215170)
+++ gcc/config/i386/netbsd-elf.h	(working copy)
@@ -119,3 +119,5 @@  along with GCC; see the file COPYING3.  If not see
 #define DEFAULT_PCC_STRUCT_RETURN 1
 
 #define HAVE_ENABLE_EXECUTE_STACK
+
+#define IX86_MAYBE_NO_LIBGCC_TFMODE
Index: gcc/config/i386/netbsd64.h
===================================================================
--- gcc/config/i386/netbsd64.h	(revision 215170)
+++ gcc/config/i386/netbsd64.h	(working copy)
@@ -67,3 +67,5 @@  along with GCC; see the file COPYING3.  If not see
 }
 
 #define HAVE_ENABLE_EXECUTE_STACK
+
+#define IX86_MAYBE_NO_LIBGCC_TFMODE
Index: gcc/config/i386/nto.h
===================================================================
--- gcc/config/i386/nto.h	(revision 215170)
+++ gcc/config/i386/nto.h	(working copy)
@@ -103,3 +103,5 @@  crti.o%s \
 #define TARGET_POSIX_IO
 
 #undef DBX_REGISTER_NUMBER
+
+#define IX86_MAYBE_NO_LIBGCC_TFMODE
Index: gcc/config/i386/openbsd.h
===================================================================
--- gcc/config/i386/openbsd.h	(revision 215170)
+++ gcc/config/i386/openbsd.h	(working copy)
@@ -99,3 +99,5 @@  along with GCC; see the file COPYING3.  If not see
 #undef ASM_QUAD
 
 #define TARGET_HAVE_NAMED_SECTIONS false
+
+#define IX86_MAYBE_NO_LIBGCC_TFMODE
Index: gcc/config/i386/openbsdelf.h
===================================================================
--- gcc/config/i386/openbsdelf.h	(revision 215170)
+++ gcc/config/i386/openbsdelf.h	(working copy)
@@ -113,6 +113,4 @@  along with GCC; see the file COPYING3.  If not see
 #define HAVE_ENABLE_EXECUTE_STACK
 
 /* Put all *tf routines in libgcc.  */
-#undef LIBGCC2_HAS_TF_MODE
-#define LIBGCC2_HAS_TF_MODE 1
 #define LIBGCC2_TF_CEXT q
Index: gcc/config/i386/rtemself.h
===================================================================
--- gcc/config/i386/rtemself.h	(revision 215170)
+++ gcc/config/i386/rtemself.h	(working copy)
@@ -38,3 +38,5 @@  along with GCC; see the file COPYING3.  If not see
 #else
 #define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 80
 #endif
+
+#define IX86_NO_LIBGCC_TFMODE
Index: gcc/config/i386/sol2.h
===================================================================
--- gcc/config/i386/sol2.h	(revision 215170)
+++ gcc/config/i386/sol2.h	(working copy)
@@ -238,6 +238,4 @@  along with GCC; see the file COPYING3.  If not see
 #endif
 
 /* Put all *tf routines in libgcc.  */
-#undef LIBGCC2_HAS_TF_MODE
-#define LIBGCC2_HAS_TF_MODE 1
 #define LIBGCC2_TF_CEXT q
Index: gcc/config/i386/vx-common.h
===================================================================
--- gcc/config/i386/vx-common.h	(revision 215170)
+++ gcc/config/i386/vx-common.h	(working copy)
@@ -31,3 +31,5 @@  along with GCC; see the file COPYING3.  If not see
 
 #undef DBX_REGISTER_NUMBER
 #define DBX_REGISTER_NUMBER(n)  svr4_dbx_register_map[n]
+
+#define IX86_MAYBE_NO_LIBGCC_TFMODE
Index: gcc/config/ia64/elf.h
===================================================================
--- gcc/config/ia64/elf.h	(revision 215170)
+++ gcc/config/ia64/elf.h	(working copy)
@@ -65,4 +65,6 @@  see the files COPYING3 and COPYING.RUNTIME respect
 			  %{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}}\
 			crti.o%s crtbegin.o%s"
 
+#define IA64_NO_LIBGCC_TFMODE
+
 /* End of elf.h */
Index: gcc/config/ia64/freebsd.h
===================================================================
--- gcc/config/ia64/freebsd.h	(revision 215170)
+++ gcc/config/ia64/freebsd.h	(working copy)
@@ -50,3 +50,5 @@  along with GCC; see the file COPYING3.  If not see
 #define TARGET_ELF		1
 
 #define JMP_BUF_SIZE  76
+
+#define IA64_NO_LIBGCC_TFMODE
Index: gcc/config/ia64/hpux.h
===================================================================
--- gcc/config/ia64/hpux.h	(revision 215170)
+++ gcc/config/ia64/hpux.h	(working copy)
@@ -189,14 +189,6 @@  do {								\
 
 #define FLOAT_LIB_COMPARE_RETURNS_BOOL(MODE, COMPARISON) ((MODE) == TFmode)
 
-/* Put all *xf routines in libgcc, regardless of long double size.  */
-#undef LIBGCC2_HAS_XF_MODE
-#define LIBGCC2_HAS_XF_MODE 1
-
-/* Put all *tf routines in libgcc, regardless of long double size.  */
-#undef LIBGCC2_HAS_TF_MODE
-#define LIBGCC2_HAS_TF_MODE 1
-
 /* HP-UX headers are C++-compatible.  */
 #define NO_IMPLICIT_EXTERN_C
 
Index: gcc/config/ia64/ia64.c
===================================================================
--- gcc/config/ia64/ia64.c	(revision 215170)
+++ gcc/config/ia64/ia64.c	(working copy)
@@ -319,6 +319,7 @@  static rtx ia64_struct_value_rtx (tree, int);
 static tree ia64_gimplify_va_arg (tree, tree, gimple_seq *, gimple_seq *);
 static bool ia64_scalar_mode_supported_p (enum machine_mode mode);
 static bool ia64_vector_mode_supported_p (enum machine_mode mode);
+static bool ia64_libgcc_floating_mode_supported_p (enum machine_mode mode);
 static bool ia64_legitimate_constant_p (enum machine_mode, rtx);
 static bool ia64_legitimate_address_p (enum machine_mode, rtx, bool);
 static bool ia64_cannot_force_const_mem (enum machine_mode, rtx);
@@ -598,6 +599,10 @@  static const struct attribute_spec ia64_attribute_
 #undef TARGET_VECTOR_MODE_SUPPORTED_P
 #define TARGET_VECTOR_MODE_SUPPORTED_P ia64_vector_mode_supported_p
 
+#undef TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P
+#define TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P \
+  ia64_libgcc_floating_mode_supported_p
+
 /* ia64 architecture manual 4.4.7: ... reads, writes, and flushes may occur
    in an order different from the specified program order.  */
 #undef TARGET_RELAXED_ORDERING
@@ -10939,6 +10944,36 @@  ia64_vector_mode_supported_p (enum machine_mode mo
     }
 }
 
+/* Implement TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P.  */
+
+static bool
+ia64_libgcc_floating_mode_supported_p (enum machine_mode mode)
+{
+  switch (mode)
+    {
+    case SFmode:
+    case DFmode:
+      return true;
+
+    case XFmode:
+#ifdef IA64_NO_LIBGCC_XFMODE
+      return false;
+#else
+      return true;
+#endif
+
+    case TFmode:
+#ifdef IA64_NO_LIBGCC_TFMODE
+      return false;
+#else
+      return true;
+#endif
+
+    default:
+      return false;
+    }
+}
+
 /* Implement the FUNCTION_PROFILER macro.  */
 
 void
Index: gcc/config/ia64/linux.h
===================================================================
--- gcc/config/ia64/linux.h	(revision 215170)
+++ gcc/config/ia64/linux.h	(working copy)
@@ -77,8 +77,6 @@  do {						\
 #define LINK_EH_SPEC ""
 
 /* 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
 
Index: gcc/config/ia64/vms.h
===================================================================
--- gcc/config/ia64/vms.h	(revision 215170)
+++ gcc/config/ia64/vms.h	(working copy)
@@ -154,3 +154,6 @@  STATIC func_ptr __CTOR_LIST__[1]
 /* Default values for _CRTL_VER and _VMS_VER.  */
 #define VMS_DEFAULT_CRTL_VER 80300000
 #define VMS_DEFAULT_VMS_VER 80300000
+
+#define IA64_NO_LIBGCC_XFMODE
+#define IA64_NO_LIBGCC_TFMODE
Index: gcc/config/msp430/msp430.h
===================================================================
--- gcc/config/msp430/msp430.h	(revision 215170)
+++ gcc/config/msp430/msp430.h	(working copy)
@@ -112,7 +112,6 @@  extern bool msp430x;
 #define DOUBLE_TYPE_SIZE 		64
 #define LONG_DOUBLE_TYPE_SIZE		64 /*DOUBLE_TYPE_SIZE*/
 
-#define LIBGCC2_HAS_DF_MODE		1
 #define LIBGCC2_LONG_DOUBLE_TYPE_SIZE   64
 
 #define DEFAULT_SIGNED_CHAR		0
Index: gcc/config/pdp11/pdp11.c
===================================================================
--- gcc/config/pdp11/pdp11.c	(revision 215170)
+++ gcc/config/pdp11/pdp11.c	(working copy)
@@ -157,6 +157,8 @@  static void pdp11_function_arg_advance (cumulative
 					enum machine_mode, const_tree, bool);
 static void pdp11_conditional_register_usage (void);
 static bool pdp11_legitimate_constant_p (enum machine_mode, rtx);
+
+static bool pdp11_scalar_mode_supported_p (enum machine_mode);
 
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_BYTE_OP
@@ -223,6 +225,9 @@  static bool pdp11_legitimate_constant_p (enum mach
 
 #undef  TARGET_LEGITIMATE_CONSTANT_P
 #define TARGET_LEGITIMATE_CONSTANT_P pdp11_legitimate_constant_p
+
+#undef  TARGET_SCALAR_MODE_SUPPORTED_P
+#define TARGET_SCALAR_MODE_SUPPORTED_P pdp11_scalar_mode_supported_p
 
 /* A helper function to determine if REGNO should be saved in the
    current function's stack frame.  */
@@ -1901,4 +1906,15 @@  pdp11_legitimate_constant_p (enum machine_mode mod
   return GET_CODE (x) != CONST_DOUBLE || legitimate_const_double_p (x);
 }
 
+/* Implement TARGET_SCALAR_MODE_SUPPORTED_P.  */
+
+static bool
+pdp11_scalar_mode_supported_p (enum machine_mode mode)
+{
+  /* Support SFmode even with -mfloat64.  */
+  if (mode == SFmode)
+    return true;
+  return default_scalar_mode_supported_p (mode);
+}
+
 struct gcc_target targetm = TARGET_INITIALIZER;
Index: gcc/config/rl78/rl78.h
===================================================================
--- gcc/config/rl78/rl78.h	(revision 215170)
+++ gcc/config/rl78/rl78.h	(working copy)
@@ -98,7 +98,6 @@ 
 #define DOUBLE_TYPE_SIZE 		32 /*64*/
 #define LONG_DOUBLE_TYPE_SIZE		64 /*DOUBLE_TYPE_SIZE*/
 
-#define LIBGCC2_HAS_DF_MODE		1
 #define LIBGCC2_LONG_DOUBLE_TYPE_SIZE   64
 
 #define DEFAULT_SIGNED_CHAR		0
Index: gcc/config/rx/rx.h
===================================================================
--- gcc/config/rx/rx.h	(revision 215170)
+++ gcc/config/rx/rx.h	(working copy)
@@ -131,10 +131,8 @@ 
 #define LONG_DOUBLE_TYPE_SIZE		DOUBLE_TYPE_SIZE
 
 #ifdef __RX_32BIT_DOUBLES__
-#define LIBGCC2_HAS_DF_MODE		0
 #define LIBGCC2_LONG_DOUBLE_TYPE_SIZE   32
 #else
-#define LIBGCC2_HAS_DF_MODE		1
 #define LIBGCC2_LONG_DOUBLE_TYPE_SIZE   64
 #endif
 
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	(revision 215170)
+++ gcc/doc/tm.texi	(working copy)
@@ -1549,29 +1549,6 @@  if you want routines in @file{libgcc2.a} for a siz
 default is @code{LONG_DOUBLE_TYPE_SIZE}.
 @end defmac
 
-@defmac LIBGCC2_HAS_DF_MODE
-Define this macro if neither @code{DOUBLE_TYPE_SIZE} nor
-@code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE} is
-@code{DFmode} but you want @code{DFmode} routines in @file{libgcc2.a}
-anyway.  If you don't define this and either @code{DOUBLE_TYPE_SIZE}
-or @code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE} is 64 then the default is 1,
-otherwise it is 0.
-@end defmac
-
-@defmac LIBGCC2_HAS_XF_MODE
-Define this macro if @code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE} is not
-@code{XFmode} but you want @code{XFmode} routines in @file{libgcc2.a}
-anyway.  If you don't define this and @code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE}
-is 80 then the default is 1, otherwise it is 0.
-@end defmac
-
-@defmac LIBGCC2_HAS_TF_MODE
-Define this macro if @code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE} is not
-@code{TFmode} but you want @code{TFmode} routines in @file{libgcc2.a}
-anyway.  If you don't define this and @code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE}
-is 128 then the default is 1, otherwise it is 0.
-@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
@@ -4226,6 +4203,14 @@  If this hook allows @code{val} to have a scalar mo
 @code{int8x8x3_t}s in registers rather than forcing them onto the stack.
 @end deftypefn
 
+@deftypefn {Target Hook} bool TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P (enum machine_mode @var{mode})
+Define this to return nonzero if libgcc provides support for the 
+floating-point mode @var{mode}, which is known to pass 
+@code{TARGET_SCALAR_MODE_SUPPORTED_P}.  The default version of this 
+hook returns true for all of @code{SFmode}, @code{DFmode}, 
+@code{XFmode} and @code{TFmode}, if such modes exist.
+@end deftypefn
+
 @deftypefn {Target Hook} bool TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P (enum machine_mode @var{mode})
 Define this to return nonzero for machine modes for which the port has
 small register classes.  If this target hook returns nonzero for a given
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in	(revision 215170)
+++ gcc/doc/tm.texi.in	(working copy)
@@ -1391,29 +1391,6 @@  if you want routines in @file{libgcc2.a} for a siz
 default is @code{LONG_DOUBLE_TYPE_SIZE}.
 @end defmac
 
-@defmac LIBGCC2_HAS_DF_MODE
-Define this macro if neither @code{DOUBLE_TYPE_SIZE} nor
-@code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE} is
-@code{DFmode} but you want @code{DFmode} routines in @file{libgcc2.a}
-anyway.  If you don't define this and either @code{DOUBLE_TYPE_SIZE}
-or @code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE} is 64 then the default is 1,
-otherwise it is 0.
-@end defmac
-
-@defmac LIBGCC2_HAS_XF_MODE
-Define this macro if @code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE} is not
-@code{XFmode} but you want @code{XFmode} routines in @file{libgcc2.a}
-anyway.  If you don't define this and @code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE}
-is 80 then the default is 1, otherwise it is 0.
-@end defmac
-
-@defmac LIBGCC2_HAS_TF_MODE
-Define this macro if @code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE} is not
-@code{TFmode} but you want @code{TFmode} routines in @file{libgcc2.a}
-anyway.  If you don't define this and @code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE}
-is 128 then the default is 1, otherwise it is 0.
-@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
@@ -3530,6 +3507,8 @@  stack.
 
 @hook TARGET_ARRAY_MODE_SUPPORTED_P
 
+@hook TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P
+
 @hook TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P
 
 @hook TARGET_FLAGS_REGNUM
Index: gcc/fortran/trans-types.c
===================================================================
--- gcc/fortran/trans-types.c	(revision 215170)
+++ gcc/fortran/trans-types.c	(working copy)
@@ -31,8 +31,8 @@  along with GCC; see the file COPYING3.  If not see
 			   BOOL_TYPE_SIZE, BITS_PER_UNIT, POINTER_SIZE,
 			   INT_TYPE_SIZE, CHAR_TYPE_SIZE, SHORT_TYPE_SIZE,
 			   LONG_TYPE_SIZE, LONG_LONG_TYPE_SIZE,
-			   FLOAT_TYPE_SIZE, DOUBLE_TYPE_SIZE,
-			   LONG_DOUBLE_TYPE_SIZE and LIBGCC2_HAS_TF_MODE.  */
+			   FLOAT_TYPE_SIZE, DOUBLE_TYPE_SIZE and
+			   LONG_DOUBLE_TYPE_SIZE.  */
 #include "tree.h"
 #include "stor-layout.h"
 #include "stringpool.h"
@@ -427,10 +427,13 @@  gfc_init_kinds (void)
       /* Only let float, double, long double and __float128 go through.
 	 Runtime support for others is not provided, so they would be
 	 useless.  */
+	if (!targetm.libgcc_floating_mode_supported_p ((enum machine_mode)
+						       mode))
+	  continue;
 	if (mode != TYPE_MODE (float_type_node)
 	    && (mode != TYPE_MODE (double_type_node))
 	    && (mode != TYPE_MODE (long_double_type_node))
-#if defined(LIBGCC2_HAS_TF_MODE) && defined(ENABLE_LIBQUADMATH_SUPPORT)
+#if defined(HAVE_TFmode) && defined(ENABLE_LIBQUADMATH_SUPPORT)
 	    && (mode != TFmode)
 #endif
 	   )
Index: gcc/genmodes.c
===================================================================
--- gcc/genmodes.c	(revision 215170)
+++ gcc/genmodes.c	(working copy)
@@ -1029,6 +1029,7 @@  enum machine_mode\n{");
 	int count_ = printf ("  %smode,", m->name);
 	printf ("%*s/* %s:%d */\n", 27 - count_, "",
 		 trim_filename (m->file), m->line);
+	printf ("#define HAVE_%smode\n", m->name);
       }
 
   puts ("  MAX_MACHINE_MODE,\n");
Index: gcc/system.h
===================================================================
--- gcc/system.h	(revision 215170)
+++ gcc/system.h	(working copy)
@@ -846,7 +846,8 @@  extern void fancy_abort (const char *, int, const
 	CAN_DEBUG_WITHOUT_FP UNLIKELY_EXECUTED_TEXT_SECTION_NAME	\
 	HOT_TEXT_SECTION_NAME LEGITIMATE_CONSTANT_P ALWAYS_STRIP_DOTDOT	\
 	OUTPUT_ADDR_CONST_EXTRA SMALL_REGISTER_CLASSES ASM_OUTPUT_IDENT	\
-	ASM_BYTE_OP MEMBER_TYPE_FORCES_BLK
+	ASM_BYTE_OP MEMBER_TYPE_FORCES_BLK LIBGCC2_HAS_SF_MODE		\
+	LIBGCC2_HAS_DF_MODE LIBGCC2_HAS_XF_MODE LIBGCC2_HAS_TF_MODE
 
 /* Target macros only used for code built for the target, that have
    moved to libgcc-tm.h or have never been present elsewhere.  */
Index: gcc/target.def
===================================================================
--- gcc/target.def	(revision 215170)
+++ gcc/target.def	(working copy)
@@ -2985,6 +2985,16 @@  If this hook allows @code{val} to have a scalar mo
  bool, (enum machine_mode mode, unsigned HOST_WIDE_INT nelems),
  hook_bool_mode_uhwi_false)
 
+DEFHOOK
+(libgcc_floating_mode_supported_p,
+ "Define this to return nonzero if libgcc provides support for the \n\
+floating-point mode @var{mode}, which is known to pass \n\
+@code{TARGET_SCALAR_MODE_SUPPORTED_P}.  The default version of this \n\
+hook returns true for all of @code{SFmode}, @code{DFmode}, \n\
+@code{XFmode} and @code{TFmode}, if such modes exist.",
+ bool, (enum machine_mode mode),
+ default_libgcc_floating_mode_supported_p)
+
 /* Compute cost of moving data from a register of class FROM to one of
    TO, using MODE.  */
 DEFHOOK
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	(revision 215170)
+++ gcc/targhooks.c	(working copy)
@@ -424,6 +424,33 @@  default_scalar_mode_supported_p (enum machine_mode
     }
 }
 
+/* Return true if libgcc supports floating-point mode MODE (known to
+   be supported as a scalar mode).  */
+
+bool
+default_libgcc_floating_mode_supported_p (enum machine_mode mode)
+{
+  switch (mode)
+    {
+#ifdef HAVE_SFmode
+    case SFmode:
+#endif
+#ifdef HAVE_DFmode
+    case DFmode:
+#endif
+#ifdef HAVE_XFmode
+    case XFmode:
+#endif
+#ifdef HAVE_TFmode
+    case TFmode:
+#endif
+      return true;
+
+    default:
+      return false;
+    }
+}
+
 /* Make some target macros useable by target-independent code.  */
 bool
 targhook_words_big_endian (void)
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h	(revision 215170)
+++ gcc/targhooks.h	(working copy)
@@ -67,6 +67,7 @@  extern bool default_print_operand_punct_valid_p (u
 extern tree default_mangle_assembler_name (const char *);
 
 extern bool default_scalar_mode_supported_p (enum machine_mode);
+extern bool default_libgcc_floating_mode_supported_p (enum machine_mode);
 extern bool targhook_words_big_endian (void);
 extern bool targhook_float_words_big_endian (void);
 extern bool default_float_exceptions_rounding_supported_p (void);
Index: libgcc/config/libbid/bid_gcc_intrinsics.h
===================================================================
--- libgcc/config/libbid/bid_gcc_intrinsics.h	(revision 215170)
+++ libgcc/config/libbid/bid_gcc_intrinsics.h	(working copy)
@@ -31,20 +31,18 @@  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
+#ifdef __LIBGCC_HAS_XF_MODE__
+#define LIBGCC2_HAS_XF_MODE 1
+#else
+#define LIBGCC2_HAS_XF_MODE 0
 #endif
 
-#ifndef LIBGCC2_HAS_XF_MODE
-#define LIBGCC2_HAS_XF_MODE \
-  (BITS_PER_UNIT == 8 && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80)
+#ifdef __LIBGCC_HAS_TF_MODE__
+#define LIBGCC2_HAS_TF_MODE 1
+#else
+#define LIBGCC2_HAS_TF_MODE 0
 #endif
 
-#ifndef LIBGCC2_HAS_TF_MODE
-#define LIBGCC2_HAS_TF_MODE \
-  (BITS_PER_UNIT == 8 && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
-#endif
-
 #ifndef BID_HAS_XF_MODE
 #define BID_HAS_XF_MODE LIBGCC2_HAS_XF_MODE
 #endif
Index: libgcc/fixed-bit.h
===================================================================
--- libgcc/fixed-bit.h	(revision 215170)
+++ libgcc/fixed-bit.h	(working copy)
@@ -45,21 +45,18 @@  see the files COPYING3 and COPYING.RUNTIME respect
    Ex: If we define FROM_QQ and TO_SI, the conversion from QQ to SI is
    generated.  */
 
-#ifndef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
+#ifdef __LIBGCC_HAS_SF_MODE__
+#define LIBGCC2_HAS_SF_MODE 1
+#else
+#define LIBGCC2_HAS_SF_MODE 0
 #endif
 
-#ifndef LIBGCC2_HAS_SF_MODE
-#define LIBGCC2_HAS_SF_MODE (BITS_PER_UNIT == 8)
+#ifdef __LIBGCC_HAS_DF_MODE__
+#define LIBGCC2_HAS_DF_MODE 1
+#else
+#define LIBGCC2_HAS_DF_MODE 0
 #endif
 
-#ifndef LIBGCC2_HAS_DF_MODE
-#define LIBGCC2_HAS_DF_MODE \
-  (BITS_PER_UNIT == 8 \
-   && (__SIZEOF_DOUBLE__ * __CHAR_BIT__ == 64 \
-       || LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64))
-#endif
-
 typedef          int QItype     __attribute__ ((mode (QI)));
 typedef unsigned int UQItype    __attribute__ ((mode (QI)));
 typedef          int HItype     __attribute__ ((mode (HI)));
Index: libgcc/libgcc2.h
===================================================================
--- libgcc/libgcc2.h	(revision 215170)
+++ libgcc/libgcc2.h	(working copy)
@@ -38,25 +38,28 @@  extern void __eprintf (const char *, const char *,
 #define LIBGCC2_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
 #endif
 
-#ifndef LIBGCC2_HAS_SF_MODE
-#define LIBGCC2_HAS_SF_MODE (BITS_PER_UNIT == 8)
+#ifdef __LIBGCC_HAS_SF_MODE__
+#define LIBGCC2_HAS_SF_MODE 1
+#else
+#define LIBGCC2_HAS_SF_MODE 0
 #endif
 
-#ifndef LIBGCC2_HAS_DF_MODE
-#define LIBGCC2_HAS_DF_MODE \
-  (BITS_PER_UNIT == 8 \
-   && (__SIZEOF_DOUBLE__ * __CHAR_BIT__ == 64 \
-       || LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64))
+#ifdef __LIBGCC_HAS_DF_MODE__
+#define LIBGCC2_HAS_DF_MODE 1
+#else
+#define LIBGCC2_HAS_DF_MODE 0
 #endif
 
-#ifndef LIBGCC2_HAS_XF_MODE
-#define LIBGCC2_HAS_XF_MODE \
-  (BITS_PER_UNIT == 8 && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80)
+#ifdef __LIBGCC_HAS_XF_MODE__
+#define LIBGCC2_HAS_XF_MODE 1
+#else
+#define LIBGCC2_HAS_XF_MODE 0
 #endif
 
-#ifndef LIBGCC2_HAS_TF_MODE
-#define LIBGCC2_HAS_TF_MODE \
-  (BITS_PER_UNIT == 8 && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
+#ifdef __LIBGCC_HAS_TF_MODE__
+#define LIBGCC2_HAS_TF_MODE 1
+#else
+#define LIBGCC2_HAS_TF_MODE 0
 #endif
 
 #ifndef __LIBGCC_SF_MANT_DIG__