[07/21] ARC: math soft float support

Message ID 1545167083-16764-8-git-send-email-vgupta@synopsys.com
State New, archived
Headers

Commit Message

Vineet Gupta Dec. 18, 2018, 9:04 p.m. UTC
  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

Joseph Myers Dec. 18, 2018, 11:23 p.m. UTC | #1
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.
  
Joseph Myers Dec. 19, 2018, 12:01 a.m. UTC | #2
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.)
  
Vineet Gupta Dec. 20, 2018, 9:35 p.m. UTC | #3
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 !
  
Vineet Gupta Dec. 21, 2018, 1:08 a.m. UTC | #4
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 !
  
Joseph Myers Dec. 21, 2018, 1:19 a.m. UTC | #5
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.
  

Patch

diff --git a/ChangeLog b/ChangeLog
index d2f6cd2d0d09..b946f57204b6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
 
diff --git a/sysdeps/arc/bits/fenv.h b/sysdeps/arc/bits/fenv.h
new file mode 100644
index 000000000000..4053f57d1094
--- /dev/null
+++ b/sysdeps/arc/bits/fenv.h
@@ -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
diff --git a/sysdeps/arc/math_private.h b/sysdeps/arc/math_private.h
new file mode 100644
index 000000000000..35046d842533
--- /dev/null
+++ b/sysdeps/arc/math_private.h
@@ -0,0 +1,6 @@ 
+#ifndef ARC_MATH_PRIVATE_H
+#define ARC_MATH_PRIVATE_H
+
+#include_next <math_private.h>
+
+#endif
diff --git a/sysdeps/arc/nofpu/Implies b/sysdeps/arc/nofpu/Implies
new file mode 100644
index 000000000000..abcbadb25f22
--- /dev/null
+++ b/sysdeps/arc/nofpu/Implies
@@ -0,0 +1 @@ 
+ieee754/soft-fp
diff --git a/sysdeps/arc/nofpu/math-tests-exception.h b/sysdeps/arc/nofpu/math-tests-exception.h
new file mode 100644
index 000000000000..bb338388d8af
--- /dev/null
+++ b/sysdeps/arc/nofpu/math-tests-exception.h
@@ -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
diff --git a/sysdeps/arc/nofpu/math-tests-rounding.h b/sysdeps/arc/nofpu/math-tests-rounding.h
new file mode 100644
index 000000000000..e371e647db13
--- /dev/null
+++ b/sysdeps/arc/nofpu/math-tests-rounding.h
@@ -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
diff --git a/sysdeps/arc/sfp-machine.h b/sysdeps/arc/sfp-machine.h
new file mode 100644
index 000000000000..95eefc187430
--- /dev/null
+++ b/sysdeps/arc/sfp-machine.h
@@ -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