"Joseph S. Myers" <jos...@codesourcery.com> writes: > I note that you're not using t-softfp-excl. Logically, it's best to use > the libgcc2.c functions in the cases where hardware floating point is > involved (when they are providing conversions to/from DImode/TImode, and > to/from unsigned, based on conversions to/from a narrower type or to/from > signed, and the floating-point type involved is a hardware type), because > that will be more efficient than a fully software implementation. But > when building for a soft-float multilib, and in any case when TFmode is > involved, it's best to use the soft-fp functions rather than the libgcc2.c > versions.
Thanks, I'd missed that. > Thus: > > * For soft-float, what you have seems optimal. > > * For hard-float o32, using t-softfp-excl would be best. > > * For hard-float n32 and n64, what's optimal would be a hybrid the > makefile code doesn't yet support, so would need custom handling in MIPS > fragments; see above, and the t-softfp comment "This list is taken from > mklibgcc.in and doesn't presently allow for 64-bit targets where si should > become di and di should become ti.". How much this matters (and indeed > how much it matters for hard-float o32) depends on which of the > conversions involving SFmode / DFmode do actually end up using a libgcc > function (for which the libgcc2.c version would be better than the soft-fp > version). I agree that would work but in the end I went for a slightly different approach. The main reason was that although libgcc2.c provides those good di and ti conversion routines you mentioned, it doesn't AFAICT provide any si routines; they used to come from fpbit.c instead. So if we're going to provide fast di and ti routines we should probably try to do the same for si. TBH, I also didn't fancy trying to change anything as sensitive as that list of exclusions in t-softfp. As you say, most of the functions with hard-float support should be used rarely if at all. I think the only reason we ended up providing a full set of routines for hard-float was because, back in the bad old days when libgcc was in gcc/, it was very difficult to tailor it to individual multilibs. That includes the set of exported symbols. So here I just provide simple C functions for each operation that has hard-float support. We can then restrict the softfp stuff to functions that really do need softfp support, meaning that softfp_exclude_libgcc2 := n should always be OK. As an added bonus it reduces the footprint of libgcc_s.so on hard-float targets. Tested on mips64-linux-gnu and mipsisa64-sde-elf. I checked all the new o32, n32 and n64 functions to make sure that they produced the expected asm and (in particular) didn't have any recursive calls. I also rechecked the list of exported symbols in each case. Does this look OK? Thanks, Richard libgcc/ * configure.ac (libgcc_cv_mips_hard_float): New. * configure: Regenerate. * config.host (mips*-*-*): Use t-hardfp-sfdf rather than t-softfp-sfdf for hard-float targets. * config/mips/t-mips (LIB2_SIDITI_CONV_FUNCS): Reinstate. (softfp_float_modes, softfp_int_modes, softfp_extensions) (softfp_truncations, softfp_exclude_libgcc2): New. * config/mips/t-hardfp-sfdf: New file. * config/mips/hardfp.c: Likewise. Index: libgcc/configure.ac =================================================================== --- libgcc/configure.ac 2014-02-04 18:11:37.078922650 +0000 +++ libgcc/configure.ac 2014-02-04 18:11:41.534950708 +0000 @@ -292,6 +292,18 @@ EOF eval `${CC-cc} -E conftest.c | grep host_address=` rm -f conftest.c +case ${host} in +mips*-*-*) + AC_CACHE_CHECK([whether the target is hard-float], + [libgcc_cv_mips_hard_float], + [AC_COMPILE_IFELSE( + [#ifndef __mips_hard_float + #error FOO + #endif], + [libgcc_cv_mips_hard_float=yes], + [libgcc_cv_mips_hard_float=no])]) +esac + # Collect host-machine-specific information. . ${srcdir}/config.host Index: libgcc/config.host =================================================================== --- libgcc/config.host 2014-02-04 18:11:37.077922644 +0000 +++ libgcc/config.host 2014-02-04 18:11:41.434950078 +0000 @@ -142,7 +142,12 @@ microblaze*-*-*) mips*-*-*) # All MIPS targets provide a full set of FP routines. cpu_type=mips - tmake_file="mips/t-mips t-softfp-sfdf" + tmake_file="mips/t-mips" + if test "${libgcc_cv_mips_hard_float}" = yes; then + tmake_file="${tmake_file} mips/t-hardfp-sfdf" + else + tmake_file="${tmake_file} t-softfp-sfdf" + fi if test "${ac_cv_sizeof_long_double}" = 16; then tmake_file="${tmake_file} mips/t-softfp-tf" fi Index: libgcc/config/mips/t-mips =================================================================== --- libgcc/config/mips/t-mips 2014-02-04 18:11:37.077922644 +0000 +++ libgcc/config/mips/t-mips 2014-02-04 18:11:41.443950135 +0000 @@ -1,1 +1,9 @@ +LIB2_SIDITI_CONV_FUNCS = yes + +softfp_float_modes := +softfp_int_modes := si di +softfp_extensions := +softfp_truncations := +softfp_exclude_libgcc2 := n + LIB2ADD_ST += $(srcdir)/config/mips/lib2funcs.c Index: libgcc/config/mips/t-hardfp-sfdf =================================================================== --- /dev/null 2014-01-30 08:06:21.701666182 +0000 +++ libgcc/config/mips/t-hardfp-sfdf 2014-02-04 18:11:41.534950708 +0000 @@ -0,0 +1,26 @@ +# We need to provide a full set of FP routines for backward-compatibility. +mips-hf-bases := \ + addM3 subM3 negM2 mulM3 divM3 \ + eqM2 neM2 geM2 gtM2 leM2 ltM2 unordM2 \ + fixMsi floatsiM floatunsiM +mips-hf-modes := sf df + +mips-hf-funcs := $(foreach m, $(mips-hf-modes), \ + $(subst M,$(m),$(mips-hf-bases))) +mips-hf-funcs += extendsfdf2 truncdfsf2 + +mips-hf-defines-for = \ + $(shell echo $1 | \ + sed "s/\(.*\)\(sf\|df\)\(si\|2\|3\|\)$$/-DFUNC=__& -DOP_\1\3 -DTYPE=\2/") + +mips-hf-o = $(patsubst %,%$(objext),$(mips-hf-funcs)) +$(mips-hf-o): %$(objext): $(srcdir)/config/mips/hardfp.c + $(gcc_compile) $(call mips-hf-defines-for, $*) -c $< $(vis_hide) -Wno-missing-prototypes +libgcc-objects += $(mips-hf-o) + +ifeq ($(enable_shared),yes) +mips-hf-s-o = $(patsubst %,%_s$(objext),$(mips-hf-funcs)) +$(mips-hf-s-o): %_s$(objext): $(srcdir)/config/mips/hardfp.c + $(gcc_s_compile) $(call mips-hf-defines-for, $*) -c $< -Wno-missing-prototypes +libgcc-s-objects += $(mips-hf-s-o) +endif Index: libgcc/config/mips/hardfp.c =================================================================== --- /dev/null 2014-01-30 08:06:21.701666182 +0000 +++ libgcc/config/mips/hardfp.c 2014-02-04 18:11:41.534950708 +0000 @@ -0,0 +1,64 @@ +/* Dummy floating-point routines for MIPS hard-float code. + Copyright (C) 2014 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + +#define sf float +#define df double + +#if defined (OP_add3) +TYPE FUNC (TYPE x, TYPE y) { return x + y; } +#elif defined (OP_sub3) +TYPE FUNC (TYPE x, TYPE y) { return x - y; } +#elif defined (OP_neg2) +TYPE FUNC (TYPE x) { return -x; } +#elif defined (OP_mul3) +TYPE FUNC (TYPE x, TYPE y) { return x * y; } +#elif defined (OP_div3) +TYPE FUNC (TYPE x, TYPE y) { return x / y; } +#elif defined (OP_eq2) +int FUNC (TYPE x, TYPE y) { return x == y; } +#elif defined (OP_ne2) +int FUNC (TYPE x, TYPE y) { return x != y; } +#elif defined (OP_ge2) +int FUNC (TYPE x, TYPE y) { return x >= y; } +#elif defined (OP_gt2) +int FUNC (TYPE x, TYPE y) { return x > y; } +#elif defined (OP_le2) +int FUNC (TYPE x, TYPE y) { return x <= y; } +#elif defined (OP_lt2) +int FUNC (TYPE x, TYPE y) { return x < y; } +#elif defined (OP_unord2) +int FUNC (TYPE x, TYPE y) { return __builtin_isunordered (x, y); } +#elif defined (OP_fixsi) +int FUNC (TYPE x) { return (int) x; } +#elif defined (OP_floatsi) +TYPE FUNC (int x) { return (TYPE) x; } +#elif defined (OP_floatunsi) +TYPE FUNC (unsigned int x) { return (TYPE) x; } +#elif defined (OP_extendsf2) +TYPE FUNC (float x) { return (TYPE) x; } +#elif defined (OP_truncdf2) +TYPE FUNC (double x) { return (TYPE) x; } +#else +#error Unknown operation +#endif