From 89f87b85eb7eb67c16051741cd1bebd34afd8e8b Mon Sep 17 00:00:00 2001 From: Eshan dhawan Date: Sun, 19 Jul 2020 01:22:53 +0530 Subject: [PATCH] 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 Signed-off-by: Eshan dhawan --- newlib/libc/machine/arm/machine/fenv-mangle.h | 53 --- .../libc/machine/arm/machine/fenv-softfloat.h | 187 ---------- newlib/libc/machine/arm/machine/fenv-vfp.h | 187 ---------- newlib/libc/machine/arm/sys/fenv.h | 66 +--- newlib/libm/machine/arm/Makefile.am | 4 +- newlib/libm/machine/arm/Makefile.in | 19 +- newlib/libm/machine/arm/fenv-softfp.c | 32 -- newlib/libm/machine/arm/fenv-vfp.c | 32 -- newlib/libm/machine/arm/fenv.c | 319 ++++++------------ 9 files changed, 127 insertions(+), 772 deletions(-) delete mode 100644 newlib/libc/machine/arm/machine/fenv-mangle.h delete mode 100644 newlib/libc/machine/arm/machine/fenv-softfloat.h delete mode 100644 newlib/libc/machine/arm/machine/fenv-vfp.h delete mode 100644 newlib/libm/machine/arm/fenv-softfp.c delete mode 100644 newlib/libm/machine/arm/fenv-vfp.c diff --git a/newlib/libc/machine/arm/machine/fenv-mangle.h b/newlib/libc/machine/arm/machine/fenv-mangle.h deleted file mode 100644 index 476f7b20c..000000000 --- a/newlib/libc/machine/arm/machine/fenv-mangle.h +++ /dev/null @@ -1,53 +0,0 @@ -/*- - * Copyright (c) 2013 Andrew Turner - * 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$ - */ - -#ifdef _FENV_MANGLE_H_ -#error Only include fenv-mangle.h once -#endif - -#define _FENV_MANGLE_H_ - -#ifndef FENV_MANGLE -#error FENV_MANGLE is undefined -#endif - -#define feclearexcept FENV_MANGLE(feclearexcept) -#define fegetexceptflag FENV_MANGLE(fegetexceptflag) -#define fesetexceptflag FENV_MANGLE(fesetexceptflag) -#define feraiseexcept FENV_MANGLE(feraiseexcept) -#define fetestexcept FENV_MANGLE(fetestexcept) -#define fegetround FENV_MANGLE(fegetround) -#define fesetround FENV_MANGLE(fesetround) -#define fegetenv FENV_MANGLE(fegetenv) -#define feholdexcept FENV_MANGLE(feholdexcept) -#define fesetenv FENV_MANGLE(fesetenv) -#define feupdateenv FENV_MANGLE(feupdateenv) -#define feenableexcept FENV_MANGLE(feenableexcept) -#define fedisableexcept FENV_MANGLE(fedisableexcept) -#define fegetexcept FENV_MANGLE(fegetexcept) - diff --git a/newlib/libc/machine/arm/machine/fenv-softfloat.h b/newlib/libc/machine/arm/machine/fenv-softfloat.h deleted file mode 100644 index 5d33e18d0..000000000 --- a/newlib/libc/machine/arm/machine/fenv-softfloat.h +++ /dev/null @@ -1,187 +0,0 @@ - /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2004-2011 David Schultz - * 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$ - */ - -#ifndef _SYS_FENV_H_ -#error "This file is meant to be included only by ." -#endif -/* the file can be added from architecture specific fenv.h file found in - *libc/sys/arch/sys * - * - * This file implements the functionality of on platforms that - * lack an FPU and use softfloat in libc for floating point. To use it, - * you must write an that provides the following: - * - * - a typedef for fenv_t, which may be an integer or struct type - * - a typedef for fexcept_t (XXX This file assumes fexcept_t is a - * simple integer type containing the exception mask.) - * - definitions of FE_* constants for the five exceptions and four - * rounding modes in IEEE 754, as described in fenv(3) - * - a definition, and the corresponding external symbol, for FE_DFL_ENV - * - a macro __set_env(env, flags, mask, rnd), which sets the given fenv_t - * from the exception flags, mask, and rounding mode - * - macros __env_flags(env), __env_mask(env), and __env_round(env), which - * extract fields from an fenv_t - * - a definition of __fenv_static - * - * If the architecture supports an optional FPU, it's recommended that you - * define fenv_t and fexcept_t to match the hardware ABI. Otherwise, it - * doesn't matter how you define them. - */ -#include - -int __softfloat_float_exception_flags; -int __softfloat_float_exception_mask; -int __softfloat_float_rounding_mode; - - -__fenv_static inline int -feclearexcept(int excepts) -{ - - __softfloat_float_exception_flags &= ~excepts; - return (0); -} - -__fenv_static inline int -fegetexceptflag(fexcept_t *flagp, int excepts) -{ - - *flagp = __softfloat_float_exception_flags & excepts; - return (0); -} - -__fenv_static inline int -fesetexceptflag(const fexcept_t *flagp, int excepts) -{ - - __softfloat_float_exception_flags &= ~excepts; - __softfloat_float_exception_flags |= *flagp & excepts; - return (0); -} - -__fenv_static inline int -feraiseexcept(int excepts) -{ - - return (excepts ? -ENOTSUP : 0); -} - -__fenv_static inline int -fetestexcept(int excepts) -{ - - return (__softfloat_float_exception_flags & excepts); -} - -__fenv_static inline int -fegetround(void) -{ - - return (__softfloat_float_rounding_mode); -} - -__fenv_static inline int -fesetround(int round) -{ - - __softfloat_float_rounding_mode = round; - return (0); -} - -__fenv_static inline int -fegetenv(fenv_t *envp) -{ - - __set_env(*envp, __softfloat_float_exception_flags, - __softfloat_float_exception_mask, __softfloat_float_rounding_mode); - return (0); -} - -__fenv_static inline int -feholdexcept(fenv_t *envp) -{ - fenv_t __env; - - fegetenv(envp); - __softfloat_float_exception_flags = 0; - __softfloat_float_exception_mask = 0; - return (0); -} - -__fenv_static inline int -fesetenv(const fenv_t *envp) -{ - - __softfloat_float_exception_flags = __env_flags(*envp); - __softfloat_float_exception_mask = __env_mask(*envp); - __softfloat_float_rounding_mode = __env_round(*envp); - return (0); -} - -__fenv_static inline int -feupdateenv(const fenv_t *envp) -{ - int __oflags = __softfloat_float_exception_flags; - - fesetenv(envp); - feraiseexcept(__oflags); - return (0); -} - -#if __BSD_VISIBLE - -/* We currently provide no external definitions of the functions below. */ - -__fenv_static inline int -feenableexcept(int __mask) -{ - int __omask = __softfloat_float_exception_mask; - - __softfloat_float_exception_mask |= __mask; - return (__omask); -} - -__fenv_static inline int -fedisableexcept(int __mask) -{ - int __omask = __softfloat_float_exception_mask; - - __softfloat_float_exception_mask &= ~__mask; - return (__omask); -} - -__fenv_static inline int -fegetexcept(void) -{ - - return (__softfloat_float_exception_mask); -} - -#endif /* __BSD_VISIBLE */ diff --git a/newlib/libc/machine/arm/machine/fenv-vfp.h b/newlib/libc/machine/arm/machine/fenv-vfp.h deleted file mode 100644 index 25d71f3ab..000000000 --- a/newlib/libc/machine/arm/machine/fenv-vfp.h +++ /dev/null @@ -1,187 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2004-2005 David Schultz - * 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 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 - -__fenv_static inline int feclearexcept(int excepts) -{ - fexcept_t __fpsr; - - vmrs_fpscr(__fpsr); - __fpsr &= ~excepts; - vmsr_fpscr(__fpsr); - return (0); -} - -__fenv_static inline int -fegetexceptflag(fexcept_t *flagp, int excepts) -{ - fexcept_t __fpsr; - - vmrs_fpscr(__fpsr); - *flagp = __fpsr & excepts; - return (0); -} - -__fenv_static inline int -fesetexceptflag(const fexcept_t *flagp, int excepts) -{ - fexcept_t __fpsr; - - vmrs_fpscr(__fpsr); - __fpsr &= ~excepts; - __fpsr |= *flagp & excepts; - vmsr_fpscr(__fpsr); - return (0); -} - -__fenv_static inline int -feraiseexcept(int excepts) -{ - fexcept_t __ex = excepts; - - fesetexceptflag(&__ex, excepts); /* XXX */ - return (0); -} - -__fenv_static inline int -fetestexcept(int excepts) -{ - fexcept_t __fpsr; - - vmrs_fpscr(__fpsr); - return (__fpsr & excepts); -} - -__fenv_static inline int -fegetround(void) -{ - fenv_t __fpsr; - - vmrs_fpscr(__fpsr); - return (__fpsr & _ROUND_MASK); -} - -__fenv_static inline int -fesetround(int round) -{ - fenv_t __fpsr; - - vmrs_fpscr(__fpsr); - __fpsr &= ~(_ROUND_MASK); - __fpsr |= round; - vmsr_fpscr(__fpsr); - return (0); -} - -__fenv_static inline int -fegetenv(fenv_t *envp) -{ - - vmrs_fpscr(*envp); - return (0); -} - -__fenv_static inline int -feholdexcept(fenv_t *envp) -{ - fenv_t __env; - - vmrs_fpscr(__env); - *envp = __env; - __env &= ~(FE_ALL_EXCEPT); - vmsr_fpscr(__env); - return (0); -} - -__fenv_static inline int -fesetenv(const fenv_t *envp) -{ - - vmsr_fpscr(*envp); - return (0); -} - -__fenv_static inline int -feupdateenv(const fenv_t *envp) -{ - fexcept_t __fpsr; - - vmrs_fpscr(__fpsr); - vmsr_fpscr(*envp); - feraiseexcept(__fpsr & FE_ALL_EXCEPT); - return (0); -} - -#if __BSD_VISIBLE - -/* We currently provide no external definitions of the functions below. */ - -__fenv_static inline int -feenableexcept(int __mask) -{ - fenv_t __old_fpsr, __new_fpsr; - - 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); -} - -__fenv_static inline int -fedisableexcept(int __mask) -{ - fenv_t __old_fpsr, __new_fpsr; - - 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); -} - -__fenv_static inline int -fegetexcept(void) -{ - fenv_t __fpsr; - - vmrs_fpscr(__fpsr); - return (__fpsr & FE_ALL_EXCEPT); -} - -#endif /* __BSD_VISIBLE */ - diff --git a/newlib/libc/machine/arm/sys/fenv.h b/newlib/libc/machine/arm/sys/fenv.h index 740995a1a..70bd57be4 100644 --- a/newlib/libc/machine/arm/sys/fenv.h +++ b/newlib/libc/machine/arm/sys/fenv.h @@ -38,10 +38,6 @@ extern "C" { #endif -#ifndef __fenv_static -#define __fenv_static static -#endif - typedef int fenv_t; typedef int fexcept_t; @@ -51,7 +47,7 @@ typedef int fexcept_t; #define FE_OVERFLOW 0x0004 #define FE_UNDERFLOW 0x0008 #define FE_INEXACT 0x0010 -#ifdef __ARM_PCS_VFP +#ifndef __SOFTFP__ #define FE_DENORMAL 0x0080 #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_DENORMAL) @@ -60,61 +56,33 @@ typedef int fexcept_t; FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) #endif - - /* Rounding modes */ -#define VFP_FE_TONEAREST 0x00000000 -#define VFP_FE_UPWARD 0x00400000 -#define VFP_FE_DOWNWARD 0x00800000 -#define VFP_FE_TOWARDZERO 0x00c00000 - -#ifdef __ARM_PCS_VFP -#define FE_TONEAREST VFP_FE_TONEAREST -#define FE_UPWARD VFP_FE_UPWARD -#define FE_DOWNWARD VFP_FE_DOWNWARD -#define FE_TOWARDZERO VFP_FE_TOWARDZERO -#else -#define FE_TONEAREST 0x0000 -#define FE_TOWARDZERO 0x0001 -#define FE_UPWARD 0x0002 -#define FE_DOWNWARD 0x0003 -#endif -#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ - FE_UPWARD | FE_TOWARDZERO) - +#define FE_TONEAREST 0x00000000 +#define FE_UPWARD 0x00400000 +#define FE_DOWNWARD 0x00800000 +#define FE_TOWARDZERO 0x00c00000 /* Default floating-point environment */ - extern const fenv_t *_fe_dfl_env; #define FE_DFL_ENV (_fe_dfl_env) -/* We need to be able to map status flag positions to mask flag positions */ -#ifndef __ARM_PCS_VFP -#define _FPUSW_SHIFT 16 -#define _ENABLE_MASK (FE_ALL_EXCEPT << _FPUSW_SHIFT) -#endif - - - -int feclearexcept(int excepts); -int fegetexceptflag(fexcept_t *flagp, int excepts); -int fesetexceptflag(const fexcept_t *flagp, int excepts); -int feraiseexcept(int excepts); -int fetestexcept(int excepts); +int feclearexcept(int); +int fegetexceptflag(fexcept_t *, int); +int fesetexceptflag(const fexcept_t *, int); +int feraiseexcept(int); +int fetestexcept(int); int fegetround(void); -int fesetround(int round); -int fegetenv(fenv_t *envp); -int feholdexcept(fenv_t *envp); -int fesetenv(const fenv_t *envp); -int feupdateenv(const fenv_t *envp); +int fesetround(int); +int fegetenv(fenv_t *); +int feholdexcept(fenv_t *); +int fesetenv(const fenv_t *); +int feupdateenv(const fenv_t *); #if __BSD_VISIBLE -int feenableexcept(int __mask); -int fedisableexcept(int __mask); +int feenableexcept(int); +int fedisableexcept(int); int fegetexcept(void); #endif /* __BSD_VISIBLE */ - - #ifdef __cplusplus } #endif diff --git a/newlib/libm/machine/arm/Makefile.am b/newlib/libm/machine/arm/Makefile.am index a64ee59d5..180a37f44 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 ecfa684e7..aa23dd4d5 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 a576cc1b2..000000000 --- a/newlib/libm/machine/arm/fenv-softfp.c +++ /dev/null @@ -1,32 +0,0 @@ -/*- - * Copyright (c) 2013 Andrew Turner - * 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 -#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 297e81296..000000000 --- a/newlib/libm/machine/arm/fenv-vfp.c +++ /dev/null @@ -1,32 +0,0 @@ -/*- - * Copyright (c) 2013 Andrew Turner - * 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 -#include "fenv.c" - diff --git a/newlib/libm/machine/arm/fenv.c b/newlib/libm/machine/arm/fenv.c index 5b61ab81f..0735cd1c5 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 + * Copyright (c) 2004-2005 David Schultz * Copyright (c) 2013 Andrew Turner * All rights reserved. * @@ -29,300 +29,195 @@ * $FreeBSD$ */ -#define __fenv_static #include -#include - -#if __ARM_ARCH >= 6 -#define FENV_ARMv6 +#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 -/* When SOFTFP_ABI is defined we are using the softfp ABI. */ -#if defined(__VFP_FP__) && !defined(__ARM_PCS_VFP) -#define SOFTFP_ABI -#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 - -#else /* __ARM_PCS_VFP PRESENT */ - -#include - -#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; +#ifndef __SOFTFP__ + fenv_t __old_fpsr, __new_fpsr; - __unmasked = 0; - if (_libc_arm_fpu_present) - __unmasked = __vfp_feenableexcept(__mask); - __unmasked |= __softfp_feenableexcept(__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 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 - +}