From 425515d0acdb7faaadac1203430f5c5849eb85a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= Date: Wed, 22 Jan 2020 02:25:46 +0100 Subject: [PATCH] m68k: really add fenv from musl-1.1.24 Somehow the first review merged only the commit log. FreeBSD doesn't have m68k anyway, so use fenv from musl with as less changes as possible. Change-Id: I6372af6679e6773fbb6bf4c8b5b30512971a97a6 Reviewed-on: https://review.haiku-os.org/c/haiku/+/3161 Reviewed-by: Alex von Gluck IV --- headers/posix/arch/m68k/fenv.h | 63 +++++++++++++ headers/posix/fenv.h | 2 + .../libroot/posix/arch/generic/fenv-generic.c | 45 +++++++++ .../libroot/posix/arch/generic/fesetround.c | 32 +++++++ src/system/libroot/posix/arch/m68k/Jamfile | 4 + src/system/libroot/posix/arch/m68k/fenv.c | 94 +++++++++++++++++++ 6 files changed, 240 insertions(+) create mode 100644 headers/posix/arch/m68k/fenv.h create mode 100644 src/system/libroot/posix/arch/generic/fenv-generic.c create mode 100644 src/system/libroot/posix/arch/generic/fesetround.c create mode 100644 src/system/libroot/posix/arch/m68k/fenv.c diff --git a/headers/posix/arch/m68k/fenv.h b/headers/posix/arch/m68k/fenv.h new file mode 100644 index 0000000000..545822daa6 --- /dev/null +++ b/headers/posix/arch/m68k/fenv.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2005-2019 Rich Felker, et al. + * + * Part of MUSL, released under the MIT license. + */ + + +#ifndef _FENV_H_ +#define _FENV_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if __HAVE_68881__ || __mcffpu__ + +#define FE_INEXACT 8 +#define FE_DIVBYZERO 16 +#define FE_UNDERFLOW 32 +#define FE_OVERFLOW 64 +#define FE_INVALID 128 + +#define FE_ALL_EXCEPT 0xf8 + +#define FE_TONEAREST 0 +#define FE_TOWARDZERO 16 +#define FE_DOWNWARD 32 +#define FE_UPWARD 48 + +#else + +#define FE_ALL_EXCEPT 0 +#define FE_TONEAREST 0 + +#endif + +typedef unsigned fexcept_t; + +typedef struct { + unsigned __control_register, __status_register, __instruction_address; +} fenv_t; + +#define FE_DFL_ENV ((const fenv_t *) -1) + +int feclearexcept(int); +int fegetexceptflag(fexcept_t *, int); +int feraiseexcept(int); +int fesetexceptflag(const fexcept_t *, int); +int fetestexcept(int); + +int fegetround(void); +int fesetround(int); + +int fegetenv(fenv_t *); +int feholdexcept(fenv_t *); +int fesetenv(const fenv_t *); +int feupdateenv(const fenv_t *); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/headers/posix/fenv.h b/headers/posix/fenv.h index 6c8c37a61c..edf44d0a96 100644 --- a/headers/posix/fenv.h +++ b/headers/posix/fenv.h @@ -15,6 +15,8 @@ # include #elif defined(__sparc__) # include +#elif defined(__M68K__) +# include #else # error There is no fenv.h for this architecture! #endif diff --git a/src/system/libroot/posix/arch/generic/fenv-generic.c b/src/system/libroot/posix/arch/generic/fenv-generic.c new file mode 100644 index 0000000000..62f8d822ae --- /dev/null +++ b/src/system/libroot/posix/arch/generic/fenv-generic.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2005-2019 Rich Felker, et al. + * + * Part of MUSL, released under the MIT license. + */ + + +#include + +/* Dummy functions for archs lacking fenv implementation */ + +int feclearexcept(int mask) +{ + return 0; +} + +int feraiseexcept(int mask) +{ + return 0; +} + +int fetestexcept(int mask) +{ + return 0; +} + +int fegetround(void) +{ + return FE_TONEAREST; +} + +int __fesetround(int r) +{ + return 0; +} + +int fegetenv(fenv_t *envp) +{ + return 0; +} + +int fesetenv(const fenv_t *envp) +{ + return 0; +} diff --git a/src/system/libroot/posix/arch/generic/fesetround.c b/src/system/libroot/posix/arch/generic/fesetround.c new file mode 100644 index 0000000000..fe40b008a2 --- /dev/null +++ b/src/system/libroot/posix/arch/generic/fesetround.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2005-2019 Rich Felker, et al. + * + * Part of MUSL, released under the MIT license. + */ + + +#include +#include + +#define hidden __attribute__((__visibility__("hidden"))) + +/* __fesetround wrapper for arch independent argument check */ + +hidden int __fesetround(int); + +int fesetround(int r) +{ + if (r != FE_TONEAREST +#ifdef FE_DOWNWARD + && r != FE_DOWNWARD +#endif +#ifdef FE_UPWARD + && r != FE_UPWARD +#endif +#ifdef FE_TOWARDZERO + && r != FE_TOWARDZERO +#endif + ) + return -1; + return __fesetround(r); +} diff --git a/src/system/libroot/posix/arch/m68k/Jamfile b/src/system/libroot/posix/arch/m68k/Jamfile index be57b3af49..bae11b07d9 100644 --- a/src/system/libroot/posix/arch/m68k/Jamfile +++ b/src/system/libroot/posix/arch/m68k/Jamfile @@ -3,13 +3,17 @@ SubDir HAIKU_TOP src system libroot posix arch m68k ; local architecture = $(TARGET_ARCH) ; UsePrivateSystemHeaders ; +UseHeaders [ FDirName $(HAIKU_TOP) headers compatibility bsd ] : true ; +#SubDirCcFlags -save-temps ; local genericSources = + fesetround.c setjmp_save_sigs.c longjmp_return.c ; MergeObject <$(TARGET_ARCH)>posix_arch_$(TARGET_ARCH).o : + fenv.c sigsetjmp.S siglongjmp.S diff --git a/src/system/libroot/posix/arch/m68k/fenv.c b/src/system/libroot/posix/arch/m68k/fenv.c new file mode 100644 index 0000000000..7d9042a947 --- /dev/null +++ b/src/system/libroot/posix/arch/m68k/fenv.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2005-2019 Rich Felker, et al. + * + * Part of MUSL, released under the MIT license. + */ + + +#include +#include + +#define hidden __attribute__((__visibility__("hidden"))) + +#if __HAVE_68881__ || __mcffpu__ + +static unsigned getsr() +{ + unsigned v; + __asm__ __volatile__ ("fmove.l %%fpsr,%0" : "=dm"(v)); + return v; +} + +static void setsr(unsigned v) +{ + __asm__ __volatile__ ("fmove.l %0,%%fpsr" : : "dm"(v)); +} + +static unsigned getcr() +{ + unsigned v; + __asm__ __volatile__ ("fmove.l %%fpcr,%0" : "=dm"(v)); + return v; +} + +static void setcr(unsigned v) +{ + __asm__ __volatile__ ("fmove.l %0,%%fpcr" : : "dm"(v)); +} + +int feclearexcept(int mask) +{ + if (mask & ~FE_ALL_EXCEPT) return -1; + setsr(getsr() & ~mask); + return 0; +} + +int feraiseexcept(int mask) +{ + if (mask & ~FE_ALL_EXCEPT) return -1; + setsr(getsr() | mask); + return 0; +} + +int fetestexcept(int mask) +{ + return getsr() & mask; +} + +int fegetround(void) +{ + return getcr() & FE_UPWARD; +} + +hidden int __fesetround(int r) +{ + setcr((getcr() & ~FE_UPWARD) | r); + return 0; +} + +int fegetenv(fenv_t *envp) +{ + envp->__control_register = getcr(); + envp->__status_register = getsr(); + __asm__ __volatile__ ("fmove.l %%fpiar,%0" + : "=dm"(envp->__instruction_address)); + return 0; +} + +int fesetenv(const fenv_t *envp) +{ + static const fenv_t default_env = { 0 }; + if (envp == FE_DFL_ENV) + envp = &default_env; + setcr(envp->__control_register); + setsr(envp->__status_register); + __asm__ __volatile__ ("fmove.l %0,%%fpiar" + : : "dm"(envp->__instruction_address)); + return 0; +} + +#else + +#include "fenv-generic.c" + +#endif