"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

Reply via email to