diff options
author | Eshan dhawan <eshandhawan51@gmail.com> | 2020-07-19 01:22:53 +0530 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2020-07-29 06:58:17 +0200 |
commit | b7a6e02dc6a5289bfa489c0e7b6539abd281e2c6 (patch) | |
tree | 349aea06970fed386d034a47cffb5e38b44d2f3f /newlib/libm | |
parent | 7b1416c3abe890c8058001d6bb795802f80270af (diff) | |
download | newlib-b7a6e02dc6a5289bfa489c0e7b6539abd281e2c6.zip newlib-b7a6e02dc6a5289bfa489c0e7b6539abd281e2c6.tar.gz newlib-b7a6e02dc6a5289bfa489c0e7b6539abd281e2c6.tar.bz2 |
arm: Fix fenv support
The previous fenv support for ARM used the soft-float implementation of
FreeBSD. Newlib uses the one from libgcc by default. They are not
compatible. Having an GCC incompatible soft-float fenv support in
Newlib makes no sense. A long-term solution could be to provide a
libgcc compatible soft-float support. This likely requires changes in
the GCC configuration. For now, provide a stub implementation for
soft-float multilibs similar to RISC-V.
Move implementation to one file and delete now unused files. Hide
implementation details. Remove function parameter names from header
file to avoid name conflicts.
Provide VFP support if __SOFTFP__ is not defined like glibc.
Reviewed-by: Sebastian Huber <sebastian.huber@embedded-brains.de>
Signed-off-by: Eshan dhawan <eshandhawan51@gmail.com>
Diffstat (limited to 'newlib/libm')
-rw-r--r-- | newlib/libm/machine/arm/Makefile.am | 4 | ||||
-rw-r--r-- | newlib/libm/machine/arm/Makefile.in | 19 | ||||
-rw-r--r-- | newlib/libm/machine/arm/fenv-softfp.c | 32 | ||||
-rw-r--r-- | newlib/libm/machine/arm/fenv-vfp.c | 32 | ||||
-rw-r--r-- | newlib/libm/machine/arm/fenv.c | 319 |
5 files changed, 110 insertions, 296 deletions
diff --git a/newlib/libm/machine/arm/Makefile.am b/newlib/libm/machine/arm/Makefile.am index a64ee59..180a37f 100644 --- a/newlib/libm/machine/arm/Makefile.am +++ b/newlib/libm/machine/arm/Makefile.am @@ -32,9 +32,7 @@ LIB_SOURCES = \ fesetexceptflag.c \ fesetround.c \ fetestexcept.c \ - feupdateenv.c \ - fenv-vfp.c \ - fenv-softfp.c + feupdateenv.c noinst_LIBRARIES = lib.a diff --git a/newlib/libm/machine/arm/Makefile.in b/newlib/libm/machine/arm/Makefile.in index ecfa684..aa23dd4 100644 --- a/newlib/libm/machine/arm/Makefile.in +++ b/newlib/libm/machine/arm/Makefile.in @@ -83,8 +83,7 @@ am__objects_1 = lib_a-e_sqrt.$(OBJEXT) lib_a-ef_sqrt.$(OBJEXT) \ lib_a-fenv.$(OBJEXT) lib_a-feraiseexcept.$(OBJEXT) \ lib_a-fesetenv.$(OBJEXT) lib_a-fesetexceptflag.$(OBJEXT) \ lib_a-fesetround.$(OBJEXT) lib_a-fetestexcept.$(OBJEXT) \ - lib_a-feupdateenv.$(OBJEXT) lib_a-fenv-vfp.$(OBJEXT) \ - lib_a-fenv-softfp.$(OBJEXT) + lib_a-feupdateenv.$(OBJEXT) am_lib_a_OBJECTS = $(am__objects_1) lib_a_OBJECTS = $(am_lib_a_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ @@ -237,9 +236,7 @@ LIB_SOURCES = \ fesetexceptflag.c \ fesetround.c \ fetestexcept.c \ - feupdateenv.c \ - fenv-vfp.c \ - fenv-softfp.c + feupdateenv.c noinst_LIBRARIES = lib.a lib_a_SOURCES = $(LIB_SOURCES) @@ -479,18 +476,6 @@ lib_a-feupdateenv.o: feupdateenv.c lib_a-feupdateenv.obj: feupdateenv.c $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-feupdateenv.obj `if test -f 'feupdateenv.c'; then $(CYGPATH_W) 'feupdateenv.c'; else $(CYGPATH_W) '$(srcdir)/feupdateenv.c'; fi` -lib_a-fenv-vfp.o: fenv-vfp.c - $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-fenv-vfp.o `test -f 'fenv-vfp.c' || echo '$(srcdir)/'`fenv-vfp.c - -lib_a-fenv-vfp.obj: fenv-vfp.c - $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-fenv-vfp.obj `if test -f 'fenv-vfp.c'; then $(CYGPATH_W) 'fenv-vfp.c'; else $(CYGPATH_W) '$(srcdir)/fenv-vfp.c'; fi` - -lib_a-fenv-softfp.o: fenv-softfp.c - $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-fenv-softfp.o `test -f 'fenv-softfp.c' || echo '$(srcdir)/'`fenv-softfp.c - -lib_a-fenv-softfp.obj: fenv-softfp.c - $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-fenv-softfp.obj `if test -f 'fenv-softfp.c'; then $(CYGPATH_W) 'fenv-softfp.c'; else $(CYGPATH_W) '$(srcdir)/fenv-softfp.c'; fi` - ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ diff --git a/newlib/libm/machine/arm/fenv-softfp.c b/newlib/libm/machine/arm/fenv-softfp.c deleted file mode 100644 index a576cc1..0000000 --- a/newlib/libm/machine/arm/fenv-softfp.c +++ /dev/null @@ -1,32 +0,0 @@ -/*- - * Copyright (c) 2013 Andrew Turner <andrew@FreeBSD.ORG> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#define FENV_MANGLE(x) __softfp_ ##x -#include <machine/fenv-mangle.h> -#include "fenv.c" - diff --git a/newlib/libm/machine/arm/fenv-vfp.c b/newlib/libm/machine/arm/fenv-vfp.c deleted file mode 100644 index 297e812..0000000 --- a/newlib/libm/machine/arm/fenv-vfp.c +++ /dev/null @@ -1,32 +0,0 @@ -/*- - * Copyright (c) 2013 Andrew Turner <andrew@FreeBSD.ORG> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#define FENV_MANGLE(x) __vfp_ ##x -#include <machine/fenv-mangle.h> -#include "fenv.c" - diff --git a/newlib/libm/machine/arm/fenv.c b/newlib/libm/machine/arm/fenv.c index 5b61ab8..0735cd1 100644 --- a/newlib/libm/machine/arm/fenv.c +++ b/newlib/libm/machine/arm/fenv.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG> + * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG> * Copyright (c) 2013 Andrew Turner <andrew@FreeBSD.ORG> * All rights reserved. * @@ -29,300 +29,195 @@ * $FreeBSD$ */ -#define __fenv_static #include <fenv.h> -#include <machine/acle-compat.h> - -#if __ARM_ARCH >= 6 -#define FENV_ARMv6 -#endif - -/* When SOFTFP_ABI is defined we are using the softfp ABI. */ -#if defined(__VFP_FP__) && !defined(__ARM_PCS_VFP) -#define SOFTFP_ABI +#ifndef __SOFTFP__ +#define vmrs_fpscr(__r) __asm __volatile("vmrs %0, fpscr" : "=&r"(__r)) +#define vmsr_fpscr(__r) __asm __volatile("vmsr fpscr, %0" : : "r"(__r)) +#define _FPU_MASK_SHIFT 8 +#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ + FE_UPWARD | FE_TOWARDZERO) #endif - -#ifndef FENV_MANGLE -/* - * Hopefully the system ID byte is immutable, so it's valid to use - * this as a default environment. - */ fenv_t __fe_dfl_env = { 0 }; const fenv_t *_fe_dfl_env = &__fe_dfl_env; -#endif - - -/* If this is a non-mangled softfp version special processing is required */ -#if defined(FENV_MANGLE) || !defined(SOFTFP_ABI) || !defined(FENV_ARMv6) - -/* - * The following macros map between the softfloat emulator's flags and - * the hardware's FPSR. The hardware this file was written for doesn't - * have rounding control bits, so we stick those in the system ID byte. - */ -#ifndef __ARM_PCS_VFP -#define __set_env(env, flags, mask, rnd) env = ((flags) \ - | (mask)<<_FPUSW_SHIFT \ - | (rnd) << 24) -#define __env_flags(env) ((env) & FE_ALL_EXCEPT) -#define __env_mask(env) (((env) >> _FPUSW_SHIFT) \ - & FE_ALL_EXCEPT) -#define __env_round(env) (((env) >> 24) & _ROUND_MASK) - -#include <machine/fenv-softfloat.h> - -#else /* __ARM_PCS_VFP PRESENT */ - -#include <machine/fenv-vfp.h> - -#endif /* __ARM_PCS_VFP */ - -#ifdef __GNUC_GNU_INLINE__ -#error "This file must be compiled with C99 'inline' semantics" -#endif - -extern inline int feclearexcept(int excepts); -extern inline int fegetexceptflag(fexcept_t *flagp, int excepts); -extern inline int fesetexceptflag(const fexcept_t *flagp, int excepts); -extern inline int feraiseexcept(int excepts); -extern inline int fetestexcept(int excepts); -extern inline int fegetround(void); -extern inline int fesetround(int round); -extern inline int fegetenv(fenv_t *envp); -extern inline int feholdexcept(fenv_t *envp); -extern inline int fesetenv(const fenv_t *envp); -extern inline int feupdateenv(const fenv_t *envp); -extern inline int feenableexcept(int __mask); -extern inline int fedisableexcept(int __mask); -extern inline int fegetexcept(void); - -#else /* !FENV_MANGLE && SOFTFP_ABI */ -/* Set by libc when the VFP unit is enabled */ - -int _libc_arm_fpu_present; - -int __softfp_feclearexcept(int excepts); -int __softfp_fegetexceptflag(fexcept_t *flagp, int excepts); -int __softfp_fesetexceptflag(const fexcept_t *flagp, int excepts); -int __softfp_feraiseexcept(int excepts); -int __softfp_fetestexcept(int excepts); -int __softfp_fegetround(void); -int __softfp_fesetround(int round); -int __softfp_fegetenv(fenv_t *envp); -int __softfp_feholdexcept(fenv_t *envp); -int __softfp_fesetenv(const fenv_t *envp); -int __softfp_feupdateenv(const fenv_t *envp); -int __softfp_feenableexcept(int __mask); -int __softfp_fedisableexcept(int __mask); -int __softfp_fegetexcept(void); - -int __vfp_feclearexcept(int excepts); -int __vfp_fegetexceptflag(fexcept_t *flagp, int excepts); -int __vfp_fesetexceptflag(const fexcept_t *flagp, int excepts); -int __vfp_feraiseexcept(int excepts); -int __vfp_fetestexcept(int excepts); -int __vfp_fegetround(void); -int __vfp_fesetround(int round); -int __vfp_fegetenv(fenv_t *envp); -int __vfp_feholdexcept(fenv_t *envp); -int __vfp_fesetenv(const fenv_t *envp); -int __vfp_feupdateenv(const fenv_t *envp); -int __vfp_feenableexcept(int __mask); -int __vfp_fedisableexcept(int __mask); -int __vfp_fegetexcept(void); - -static int -__softfp_round_to_vfp(int round) -{ - - switch (round) { - case FE_TONEAREST: - default: - return VFP_FE_TONEAREST; - case FE_TOWARDZERO: - return VFP_FE_TOWARDZERO; - case FE_UPWARD: - return VFP_FE_UPWARD; - case FE_DOWNWARD: - return VFP_FE_DOWNWARD; - } -} - -static int -__softfp_round_from_vfp(int round) -{ - - switch (round) { - case VFP_FE_TONEAREST: - default: - return FE_TONEAREST; - case VFP_FE_TOWARDZERO: - return FE_TOWARDZERO; - case VFP_FE_UPWARD: - return FE_UPWARD; - case VFP_FE_DOWNWARD: - return FE_DOWNWARD; - } -} int feclearexcept(int excepts) { +#ifndef __SOFTFP__ + fexcept_t __fpsr; - if (_libc_arm_fpu_present) - __vfp_feclearexcept(excepts); - __softfp_feclearexcept(excepts); - + vmrs_fpscr(__fpsr); + __fpsr &= ~excepts; + vmsr_fpscr(__fpsr); +#endif return (0); } int fegetexceptflag(fexcept_t *flagp, int excepts) { - fexcept_t __vfp_flagp; - - __vfp_flagp = 0; - if (_libc_arm_fpu_present) - __vfp_fegetexceptflag(&__vfp_flagp, excepts); - __softfp_fegetexceptflag(flagp, excepts); - - *flagp |= __vfp_flagp; +#ifndef __SOFTFP__ + fexcept_t __fpsr; + vmrs_fpscr(__fpsr); + __fpsr &= ~excepts; + __fpsr |= *flagp & excepts; + vmsr_fpscr(__fpsr); +#endif return (0); } int fesetexceptflag(const fexcept_t *flagp, int excepts) { +#ifndef __SOFTFP__ + fexcept_t __fpsr; - if (_libc_arm_fpu_present) - __vfp_fesetexceptflag(flagp, excepts); - __softfp_fesetexceptflag(flagp, excepts); - + vmrs_fpscr(__fpsr); + __fpsr &= ~excepts; + __fpsr |= *flagp & excepts; + vmsr_fpscr(__fpsr); +#endif return (0); } int feraiseexcept(int excepts) { +#ifndef __SOFTFP__ + fexcept_t __ex = excepts; - if (_libc_arm_fpu_present) - __vfp_feraiseexcept(excepts); - __softfp_feraiseexcept(excepts); - + fesetexceptflag(&__ex, excepts); +#endif return (0); } int fetestexcept(int excepts) { - int __got_excepts; +#ifndef __SOFTFP__ + fexcept_t __fpsr; - __got_excepts = 0; - if (_libc_arm_fpu_present) - __got_excepts = __vfp_fetestexcept(excepts); - __got_excepts |= __softfp_fetestexcept(excepts); - - return (__got_excepts); + vmrs_fpscr(__fpsr); + return (__fpsr & excepts); +#else + return (0); +#endif } int fegetround(void) { +#ifndef __SOFTFP__ + fenv_t __fpsr; - if (_libc_arm_fpu_present) - return __softfp_round_from_vfp(__vfp_fegetround()); - return __softfp_fegetround(); + vmrs_fpscr(__fpsr); + return (__fpsr & _ROUND_MASK); +#else +#ifdef FE_TONEAREST + return (FE_TONEAREST); +#else + return (0); +#endif +#endif } int fesetround(int round) { +#ifndef __SOFTFP__ + fenv_t __fpsr; - if (_libc_arm_fpu_present) - __vfp_fesetround(__softfp_round_to_vfp(round)); - __softfp_fesetround(round); - + vmrs_fpscr(__fpsr); + __fpsr &= ~(_ROUND_MASK); + __fpsr |= round; + vmsr_fpscr(__fpsr); +#endif return (0); } int fegetenv(fenv_t *envp) { - fenv_t __vfp_envp; - - __vfp_envp = 0; - if (_libc_arm_fpu_present) - __vfp_fegetenv(&__vfp_envp); - __softfp_fegetenv(envp); - *envp |= __vfp_envp; +#ifndef __SOFTFP__ + vmrs_fpscr(*envp); +#endif return (0); } int feholdexcept(fenv_t *envp) { - fenv_t __vfp_envp; - - __vfp_envp = 0; - if (_libc_arm_fpu_present) - __vfp_feholdexcept(&__vfp_envp); - __softfp_feholdexcept(envp); - *envp |= __vfp_envp; +#ifndef __SOFTFP__ + fenv_t __env; + vmrs_fpscr(__env); + *envp = __env; + __env &= ~(FE_ALL_EXCEPT); + vmsr_fpscr(__env); +#endif return (0); } int fesetenv(const fenv_t *envp) { - if (_libc_arm_fpu_present) - __vfp_fesetenv(envp); - __softfp_fesetenv(envp); - +#ifndef __SOFTFP__ + vmsr_fpscr(*envp); +#endif return (0); } int feupdateenv(const fenv_t *envp) { +#ifndef __SOFTFP__ + fexcept_t __fpsr; - if (_libc_arm_fpu_present) - __vfp_feupdateenv(envp); - __softfp_feupdateenv(envp); - + vmrs_fpscr(__fpsr); + vmsr_fpscr(*envp); + feraiseexcept(__fpsr & FE_ALL_EXCEPT); +#else +#if defined(FE_NOMASK_ENV) && FE_ALL_EXCEPT != 0 + if (envp == FE_NOMASK_ENV) + return (1); +#endif +#endif return (0); } int feenableexcept(int __mask) { - int __unmasked; - - __unmasked = 0; - if (_libc_arm_fpu_present) - __unmasked = __vfp_feenableexcept(__mask); - __unmasked |= __softfp_feenableexcept(__mask); +#ifndef __SOFTFP__ + fenv_t __old_fpsr, __new_fpsr; - return (__unmasked); + vmrs_fpscr(__old_fpsr); + __new_fpsr = __old_fpsr | + ((__mask & FE_ALL_EXCEPT) << _FPU_MASK_SHIFT); + vmsr_fpscr(__new_fpsr); + return ((__old_fpsr >> _FPU_MASK_SHIFT) & FE_ALL_EXCEPT); +#else + return (0); +#endif } int fedisableexcept(int __mask) { - int __unmasked; +#ifndef __SOFTFP__ + fenv_t __old_fpsr, __new_fpsr; - __unmasked = 0; - if (_libc_arm_fpu_present) - __unmasked = __vfp_fedisableexcept(__mask); - __unmasked |= __softfp_fedisableexcept(__mask); - - return (__unmasked); + vmrs_fpscr(__old_fpsr); + __new_fpsr = __old_fpsr & + ~((__mask & FE_ALL_EXCEPT) << _FPU_MASK_SHIFT); + vmsr_fpscr(__new_fpsr); + return ((__old_fpsr >> _FPU_MASK_SHIFT) & FE_ALL_EXCEPT); +#else + return (0); +#endif } int fegetexcept(void) { - int __unmasked; - - __unmasked = 0; - if (_libc_arm_fpu_present) - __unmasked = __vfp_fegetexcept(); - __unmasked |= __softfp_fegetexcept(); - - return (__unmasked); -} +#ifndef __SOFTFP__ + fenv_t __fpsr; + vmrs_fpscr(__fpsr); + return (__fpsr & FE_ALL_EXCEPT); +#else + return (0); #endif - +} |