[07/21] ARC: math soft float support
Commit Message
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
---
ChangeLog | 6 +++
sysdeps/arc/bits/fenv.h | 92 ++++++++++++++++++++++++++++++++
sysdeps/arc/math_private.h | 6 +++
sysdeps/arc/nofpu/Implies | 1 +
sysdeps/arc/nofpu/math-tests-exception.h | 27 ++++++++++
sysdeps/arc/nofpu/math-tests-rounding.h | 27 ++++++++++
sysdeps/arc/sfp-machine.h | 51 ++++++++++++++++++
7 files changed, 210 insertions(+)
create mode 100644 sysdeps/arc/bits/fenv.h
create mode 100644 sysdeps/arc/math_private.h
create mode 100644 sysdeps/arc/nofpu/Implies
create mode 100644 sysdeps/arc/nofpu/math-tests-exception.h
create mode 100644 sysdeps/arc/nofpu/math-tests-rounding.h
create mode 100644 sysdeps/arc/sfp-machine.h
Comments
On Tue, 18 Dec 2018, Vineet Gupta wrote:
> +#if defined(__ARC_FPU_SP__) || defined(__ARC_FPU_DP__)
Missing spaces before '(' (should have such spaces in most cases between
an identifier or keyword and '(' - calls to "defined", calls to functions,
calls to macros, __attribute__, etc. - except for a few cases of calls to
macros such as ElfW where the result is logically used like an
identifier).
> +/* In the soft-float case, only rounding to nearest is supported, with
> + no exceptions. */
To confirm: hard-float and soft-float are always different ABIs; you don't
support hard-float compilation using the soft-float function calling ABI
(like is supported for ARM and RISC-V, for example)? (If you support
hard-float compilation with the soft-float ABI, it would be problematic to
have different FE_TONEAREST values in the two cases - ARM and RISC-V both
define all the FE_* macros independently of whether hard or soft float is
used, because they support that case.)
> diff --git a/sysdeps/arc/math_private.h b/sysdeps/arc/math_private.h
This file should not be needed now.
> diff --git a/sysdeps/arc/nofpu/math-tests-exception.h b/sysdeps/arc/nofpu/math-tests-exception.h
This file does nothing (the name is wrong, the name actually used is
math-tests-exceptions.h). And it should not be needed unless you support
hard-float compilation with the soft-float ABI (and thus define all the
FE_* names in bits/fenv.h even for soft-float).
> diff --git a/sysdeps/arc/nofpu/math-tests-rounding.h b/sysdeps/arc/nofpu/math-tests-rounding.h
Again, not needed unless hard-float compilation with the soft-float ABI is
supported and bits/fenv.h has corresponding contents.
On Tue, 18 Dec 2018, Joseph Myers wrote:
> On Tue, 18 Dec 2018, Vineet Gupta wrote:
>
> > +#if defined(__ARC_FPU_SP__) || defined(__ARC_FPU_DP__)
>
> Missing spaces before '(' (should have such spaces in most cases between
> an identifier or keyword and '(' - calls to "defined", calls to functions,
> calls to macros, __attribute__, etc. - except for a few cases of calls to
> macros such as ElfW where the result is logically used like an
> identifier).
Or, of course, just omit the parentheses in the "defined" case, which is
very common for calls to "defined" in glibc.
(Function-like macro definitions are a case where you *can't* have the
space because the syntax of C requires no space between the name of the
macro being defined and the '(' before the list of argument names.)
On 12/18/18 4:01 PM, Joseph Myers wrote:
> On Tue, 18 Dec 2018, Joseph Myers wrote:
>
>> On Tue, 18 Dec 2018, Vineet Gupta wrote:
>>
>>> +#if defined(__ARC_FPU_SP__) || defined(__ARC_FPU_DP__)
>> Missing spaces before '(' (should have such spaces in most cases between
>> an identifier or keyword and '(' - calls to "defined", calls to functions,
>> calls to macros, __attribute__, etc. - except for a few cases of calls to
>> macros such as ElfW where the result is logically used like an
>> identifier).
> Or, of course, just omit the parentheses in the "defined" case, which is
> very common for calls to "defined" in glibc.
>
> (Function-like macro definitions are a case where you *can't* have the
> space because the syntax of C requires no space between the name of the
> macro being defined and the '(' before the list of argument names.)
Ok, done !
On 12/18/18 3:23 PM, Joseph Myers wrote:
> On Tue, 18 Dec 2018, Vineet Gupta wrote:
>
>> +#if defined(__ARC_FPU_SP__) || defined(__ARC_FPU_DP__)
>
> Missing spaces before '(' (should have such spaces in most cases between
> an identifier or keyword and '(' - calls to "defined", calls to functions,
> calls to macros, __attribute__, etc. - except for a few cases of calls to
> macros such as ElfW where the result is logically used like an
> identifier).
OK, I removed the parens in this case (update: removed the guard altogether, see
below).
>> +/* In the soft-float case, only rounding to nearest is supported, with
>> + no exceptions. */
>
> To confirm: hard-float and soft-float are always different ABIs; you don't
> support hard-float compilation using the soft-float function calling ABI
> (like is supported for ARM and RISC-V, for example)?
I'm still ramping up on hard-float, so pardon some of my naivety. It seems the
function calling convention is no different for soft-float vs. hard-float. We have
a single register file (hard FP instructions inherently use an additional
accumulator but that isn't really passed around so doesn't affect calling
convention). Other than that SP values go normally in a reg, DP go in reg pair
just as any 64bit value.
OTOH, the ARC libgcc float emulation code seems likely to be limited in terms of
rounding modes supported etc (the current code is dense math implemented in ARC
assembly (really not my cup of coffee) so I couldn't be sure :-(
At any rate, assuming it did limit the rounding modes etc, does that also lend
into the ABI we are talking about here ? Likely not.
> (If you support
> hard-float compilation with the soft-float ABI, it would be problematic to
> have different FE_TONEAREST values in the two cases - ARM and RISC-V both
> define all the FE_* macros independently of whether hard or soft float is
> used, because they support that case.)
I'd much rather have them be the same. The fenv.h I started with didn't
distinguish these (well it only had 1 rounding mode: FE_TONEAREST so was bogus at
best). When I revered it up, I added the various modes etc w/o the header guard
and ho behold all the math tests started failing. My knee jerk response was to
segregate them which likely papered over the issue.
>> diff --git a/sysdeps/arc/math_private.h b/sysdeps/arc/math_private.h
>
> This file should not be needed now.
Ok deleted.
>> diff --git a/sysdeps/arc/nofpu/math-tests-exception.h b/sysdeps/arc/nofpu/math-tests-exception.h
>
> This file does nothing (the name is wrong, the name actually used is
> math-tests-exceptions.h). And it should not be needed unless you support
> hard-float compilation with the soft-float ABI (and thus define all the
> FE_* names in bits/fenv.h even for soft-float).
File renamed and retained.
>> diff --git a/sysdeps/arc/nofpu/math-tests-rounding.h b/sysdeps/arc/nofpu/math-tests-rounding.h
>
> Again, not needed unless hard-float compilation with the soft-float ABI is
> supported and bits/fenv.h has corresponding contents.
ditto !
Now trying a rebuilt with these changes !
On Thu, 20 Dec 2018, Vineet Gupta wrote:
> I'm still ramping up on hard-float, so pardon some of my naivety. It seems the
> function calling convention is no different for soft-float vs. hard-float. We have
> a single register file (hard FP instructions inherently use an additional
> accumulator but that isn't really passed around so doesn't affect calling
> convention). Other than that SP values go normally in a reg, DP go in reg pair
> just as any 64bit value.
If you have only a single register file and the same calling convention -
and all struct layouts etc. are also the same - then indeed that would be
a single ABI (meaning that you only need one dynamic linker name for ARC
rather than two, if you only support one endianness). (On architectures
with separate register files, jmp_buf, ucontext etc. might sometimes
differ between hard and soft float, although often the space is still
there in the soft-float case, just not used.)
The ARM and RISC-V cases are ones where there are separate hard-float and
soft-float calling conventions - but *also* support for using hardware
floating point with the soft-float calling convention.
If you do have a single ABI, that indicates having bits/fenv.h contents
unconditional (because a soft-float compilation might legitimately end up
linking with a hard-float libm) - and thus indeed needing the internal
headers to disable certain math tests for soft-float. fpu_control.h
contents would still be conditional, however.
@@ -38,6 +38,12 @@
* sysdeps/arc/atomic-machine.h: New file.
* sysdeps/arc/nptl/bits/pthreadtypes-arch.h: New file.
* sysdeps/arc/nptl/bits/semaphore.h: New file.
+ * sysdeps/arc/bits/fenv.h: New file.
+ * sysdeps/arc/math_private.h: New file.
+ * sysdeps/arc/nofpu/Implies: New file.
+ * sysdeps/arc/nofpu/math-tests-exception.h: New file.
+ * sysdeps/arc/nofpu/math-tests-rounding.h: New file.
+ * sysdeps/arc/sfp-machine.h: New file.
2018-12-17 Joseph Myers <joseph@codesourcery.com>
new file mode 100644
@@ -0,0 +1,92 @@
+/* Copyright (C) 2012-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _FENV_H
+# error "Never use <bits/fenv.h> directly; include <fenv.h> instead."
+#endif
+
+#if defined(__ARC_FPU_SP__) || defined(__ARC_FPU_DP__)
+
+enum
+ {
+ FE_INVALID =
+#define FE_INVALID (0x01)
+ FE_INVALID,
+ FE_DIVBYZERO =
+#define FE_DIVBYZERO (0x02)
+ FE_DIVBYZERO,
+ FE_OVERFLOW =
+#define FE_OVERFLOW (0x04)
+ FE_OVERFLOW,
+ FE_UNDERFLOW =
+#define FE_UNDERFLOW (0x08)
+ FE_UNDERFLOW,
+ FE_INEXACT =
+#define FE_INEXACT (0x10)
+ FE_INEXACT
+ };
+
+#define FE_ALL_EXCEPT \
+ (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT)
+
+enum
+ {
+ FE_TOWARDZERO =
+#define FE_TOWARDZERO (0x0)
+ FE_TOWARDZERO,
+ FE_TONEAREST =
+#define FE_TONEAREST (0x1)
+ FE_TONEAREST,
+ FE_UPWARD =
+#define FE_UPWARD (0x2)
+ FE_UPWARD,
+ FE_DOWNWARD =
+#define FE_DOWNWARD (0x3)
+ FE_DOWNWARD
+ };
+
+#else
+
+/* In the soft-float case, only rounding to nearest is supported, with
+ no exceptions. */
+
+enum
+ {
+ __FE_UNDEFINED = -1,
+
+ FE_TONEAREST =
+# define FE_TONEAREST 0x0
+ FE_TONEAREST
+ };
+
+# define FE_ALL_EXCEPT 0
+
+#endif
+
+typedef unsigned int fexcept_t;
+typedef unsigned int fenv_t;
+
+/* If the default argument is used we use this value. */
+#define FE_DFL_ENV ((const fenv_t *) -1)
+
+#if __GLIBC_USE (IEC_60559_BFP_EXT)
+/* Type representing floating-point control modes. */
+typedef unsigned int femode_t;
+
+/* Default floating-point control modes. */
+# define FE_DFL_MODE ((const femode_t *) -1L)
+#endif
new file mode 100644
@@ -0,0 +1,6 @@
+#ifndef ARC_MATH_PRIVATE_H
+#define ARC_MATH_PRIVATE_H
+
+#include_next <math_private.h>
+
+#endif
new file mode 100644
@@ -0,0 +1 @@
+ieee754/soft-fp
new file mode 100644
@@ -0,0 +1,27 @@
+/* Configuration for math tests. exceptions support ARC version.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef ARC_NOFPU_MATH_TESTS_EXCEPTIONS_H
+#define ARC_NOFPU_MATH_TESTS_EXCEPTIONS_H 1
+
+/* soft-float doesnot support exceptions */
+#define EXCEPTION_TESTS_float 0
+#define EXCEPTION_TESTS_double 0
+#define EXCEPTION_TESTS_long_double 0
+
+#endif
new file mode 100644
@@ -0,0 +1,27 @@
+/* Configuration for math tests: rounding mode support. ARC version.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef ARC_NOFPU_MATH_TESTS_ROUNDING_H
+#define ARC_NOFPU_MATH_TESTS_ROUNDING_H 1
+
+/* soft-float only supports to-nearest rounding mode */
+#define ROUNDING_TESTS_float(MODE) ((MODE) == FE_TONEAREST)
+#define ROUNDING_TESTS_double(MODE) ((MODE) == FE_TONEAREST)
+#define ROUNDING_TESTS_long_double(MODE) ((MODE) == FE_TONEAREST)
+
+#endif
new file mode 100644
@@ -0,0 +1,51 @@
+#define _FP_W_TYPE_SIZE 32
+#define _FP_W_TYPE unsigned long
+#define _FP_WS_TYPE signed long
+#define _FP_I_TYPE long
+
+#define _FP_MUL_MEAT_S(R,X,Y) \
+ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_D(R,X,Y) \
+ _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y) \
+ _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_MUL_MEAT_DW_S(R,X,Y) \
+ _FP_MUL_MEAT_DW_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_DW_D(R,X,Y) \
+ _FP_MUL_MEAT_DW_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_DW_Q(R,X,Y) \
+ _FP_MUL_MEAT_DW_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_loop(S,R,X,Y)
+#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y)
+
+#define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1)
+#define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1), -1
+#define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
+#define _FP_NANSIGN_S 0
+#define _FP_NANSIGN_D 0
+#define _FP_NANSIGN_Q 0
+
+#define _FP_KEEPNANFRACP 1
+#define _FP_QNANNEGATEDP 0
+
+/* This is arbitrarily taken from the PowerPC version. */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \
+ do { \
+ if ((_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs) \
+ && !(_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs)) \
+ { \
+ R##_s = Y##_s; \
+ _FP_FRAC_COPY_##wc(R,Y); \
+ } \
+ else \
+ { \
+ R##_s = X##_s; \
+ _FP_FRAC_COPY_##wc(R,X); \
+ } \
+ R##_c = FP_CLS_NAN; \
+ } while (0)
+
+#define _FP_TININESS_AFTER_ROUNDING 0