diff options
| author | Ruslan Bukin <br@FreeBSD.org> | 2016-10-31 15:33:58 +0000 |
|---|---|---|
| committer | Ruslan Bukin <br@FreeBSD.org> | 2016-10-31 15:33:58 +0000 |
| commit | 5bca221511e448277905383c6c08180e624c7460 (patch) | |
| tree | 6e8b7ee360ff41786ad352e2b2797425cfbd6255 /lib | |
| parent | ad9f2cecd74098261d39c1b2a0e85908fa9e122f (diff) | |
Notes
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/libc/Makefile | 2 | ||||
| -rw-r--r-- | lib/libc/mips/Makefile.inc | 2 | ||||
| -rw-r--r-- | lib/libc/mips/Symbol.map | 4 | ||||
| -rw-r--r-- | lib/libc/mips/gen/Makefile.inc | 2 | ||||
| -rw-r--r-- | lib/libc/mips/gen/flt_rounds.c | 20 | ||||
| -rw-r--r-- | lib/msun/mips/Makefile.inc | 4 | ||||
| -rw-r--r-- | lib/msun/mips/Symbol.map | 8 | ||||
| -rw-r--r-- | lib/msun/mips/fenv.c | 14 | ||||
| -rw-r--r-- | lib/msun/mips/fenv.h | 166 |
9 files changed, 160 insertions, 62 deletions
diff --git a/lib/libc/Makefile b/lib/libc/Makefile index a97b6fcdedb41..99ddfc2e8f7fb 100644 --- a/lib/libc/Makefile +++ b/lib/libc/Makefile @@ -111,7 +111,7 @@ NOASM= .include "${LIBC_SRCTOP}/xdr/Makefile.inc" .if (${LIBC_ARCH} == "arm" && \ (${MACHINE_ARCH:Marmv6*} == "" || (defined(CPUTYPE) && ${CPUTYPE:M*soft*}))) || \ - ${LIBC_ARCH} == "mips" + (${LIBC_ARCH} == "mips" && ${MACHINE_ARCH:Mmips*hf} == "") .include "${LIBC_SRCTOP}/softfloat/Makefile.inc" .endif .if ${LIBC_ARCH} == "i386" || ${LIBC_ARCH} == "amd64" diff --git a/lib/libc/mips/Makefile.inc b/lib/libc/mips/Makefile.inc index 4ec20d47d1dd3..54ce38e49bfa9 100644 --- a/lib/libc/mips/Makefile.inc +++ b/lib/libc/mips/Makefile.inc @@ -1,7 +1,9 @@ # $NetBSD: Makefile.inc,v 1.7 2005/09/17 11:49:39 tsutsui Exp $ # $FreeBSD$ +.if ${MACHINE_ARCH:Mmips*hf} == "" CFLAGS+=-DSOFTFLOAT +.endif MDSRCS+= machdep_ldisd.c SYM_MAPS+= ${LIBC_SRCTOP}/mips/Symbol.map diff --git a/lib/libc/mips/Symbol.map b/lib/libc/mips/Symbol.map index 38680807adc4c..9791359c93f60 100644 --- a/lib/libc/mips/Symbol.map +++ b/lib/libc/mips/Symbol.map @@ -31,6 +31,10 @@ FBSD_1.0 { sbrk; }; +FBSD_1.3 { + __flt_rounds; +}; + FBSDprivate_1.0 { /* PSEUDO syscalls */ __sys_getlogin; diff --git a/lib/libc/mips/gen/Makefile.inc b/lib/libc/mips/gen/Makefile.inc index a186fda620363..56fa380f7777a 100644 --- a/lib/libc/mips/gen/Makefile.inc +++ b/lib/libc/mips/gen/Makefile.inc @@ -1,7 +1,7 @@ # $NetBSD: Makefile.inc,v 1.27 2005/10/07 17:16:40 tsutsui Exp $ # $FreeBSD$ -SRCS+= infinity.c fabs.c ldexp.c +SRCS+= infinity.c fabs.c ldexp.c flt_rounds.c # SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \ # fpsetround.c fpsetsticky.c diff --git a/lib/libc/mips/gen/flt_rounds.c b/lib/libc/mips/gen/flt_rounds.c index 9fc64a5370533..73428d907d116 100644 --- a/lib/libc/mips/gen/flt_rounds.c +++ b/lib/libc/mips/gen/flt_rounds.c @@ -11,7 +11,14 @@ __FBSDID("$FreeBSD$"); __RCSID("$NetBSD: flt_rounds.c,v 1.5 2005/12/24 23:10:08 perry Exp $"); #endif /* LIBC_SCCS and not lint */ -#include <machine/float.h> +#include <fenv.h> +#include <float.h> + +#ifdef SOFTFLOAT +#include "softfloat-for-gcc.h" +#include "milieu.h" +#include "softfloat.h" +#endif static const int map[] = { 1, /* round to nearest */ @@ -23,8 +30,13 @@ static const int map[] = { int __flt_rounds() { - int x; + int mode; + +#ifdef SOFTFLOAT + mode = __softfloat_float_rounding_mode; +#else + __asm __volatile("cfc1 %0,$31" : "=r" (mode)); +#endif - __asm("cfc1 %0,$31" : "=r" (x)); - return map[x & 0x03]; + return map[mode & 0x03]; } diff --git a/lib/msun/mips/Makefile.inc b/lib/msun/mips/Makefile.inc index 8c1a4864f4cfa..b05f4fa3812b0 100644 --- a/lib/msun/mips/Makefile.inc +++ b/lib/msun/mips/Makefile.inc @@ -1,4 +1,8 @@ # $FreeBSD$ +.if ${MACHINE_ARCH:Mmips*hf} == "" +CFLAGS+=-DSOFTFLOAT +.endif + LDBL_PREC = 53 SYM_MAPS += ${.CURDIR}/mips/Symbol.map diff --git a/lib/msun/mips/Symbol.map b/lib/msun/mips/Symbol.map index 971112e30c8a4..081294cf55628 100644 --- a/lib/msun/mips/Symbol.map +++ b/lib/msun/mips/Symbol.map @@ -5,9 +5,17 @@ FBSD_1.0 { }; FBSD_1.3 { + feclearexcept; + fegetexceptflag; fesetexceptflag; feraiseexcept; + fetestexcept; + fegetround; + fesetround; fegetenv; feholdexcept; feupdateenv; + feenableexcept; + fedisableexcept; + fegetexcept; }; diff --git a/lib/msun/mips/fenv.c b/lib/msun/mips/fenv.c index a5a5c03d3a746..64beb704c74e6 100644 --- a/lib/msun/mips/fenv.c +++ b/lib/msun/mips/fenv.c @@ -39,6 +39,17 @@ */ const fenv_t __fe_dfl_env = 0; +#ifdef SOFTFLOAT +#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 "fenv-softfloat.h" +#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); @@ -50,3 +61,6 @@ 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); diff --git a/lib/msun/mips/fenv.h b/lib/msun/mips/fenv.h index f11499806bea7..498af3471b5dc 100644 --- a/lib/msun/mips/fenv.h +++ b/lib/msun/mips/fenv.h @@ -39,11 +39,21 @@ typedef __uint32_t fenv_t; typedef __uint32_t fexcept_t; /* Exception flags */ +#ifdef SOFTFLOAT +#define _FPUSW_SHIFT 16 #define FE_INVALID 0x0001 #define FE_DIVBYZERO 0x0002 #define FE_OVERFLOW 0x0004 #define FE_UNDERFLOW 0x0008 #define FE_INEXACT 0x0010 +#else +#define _FCSR_CAUSE_SHIFT 10 +#define FE_INVALID 0x0040 +#define FE_DIVBYZERO 0x0020 +#define FE_OVERFLOW 0x0010 +#define FE_UNDERFLOW 0x0008 +#define FE_INEXACT 0x0004 +#endif #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) @@ -61,104 +71,135 @@ 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 */ -#define _FPUSW_SHIFT 16 -#define _ENABLE_MASK (FE_ALL_EXCEPT << _FPUSW_SHIFT) +#define _ENABLE_SHIFT 5 +#define _ENABLE_MASK (FE_ALL_EXCEPT << _ENABLE_SHIFT) -#ifdef ARM_HARD_FLOAT -#define __rfs(__fpsr) __asm __volatile("rfs %0" : "=r" (*(__fpsr))) -#define __wfs(__fpsr) __asm __volatile("wfs %0" : : "r" (__fpsr)) -#else -#define __rfs(__fpsr) -#define __wfs(__fpsr) +#ifndef SOFTFLOAT +#define __cfc1(__fcsr) __asm __volatile("cfc1 %0, $31" : "=r" (__fcsr)) +#define __ctc1(__fcsr) __asm __volatile("ctc1 %0, $31" :: "r" (__fcsr)) #endif +#ifdef SOFTFLOAT +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 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); +#else __fenv_static inline int feclearexcept(int __excepts) { - fexcept_t __fpsr; + fexcept_t fcsr; + + __excepts &= FE_ALL_EXCEPT; + __cfc1(fcsr); + fcsr &= ~(__excepts | (__excepts << _FCSR_CAUSE_SHIFT)); + __ctc1(fcsr); - __rfs(&__fpsr); - __fpsr &= ~__excepts; - __wfs(__fpsr); return (0); } __fenv_static inline int fegetexceptflag(fexcept_t *__flagp, int __excepts) { - fexcept_t __fpsr; + fexcept_t fcsr; + + __excepts &= FE_ALL_EXCEPT; + __cfc1(fcsr); + *__flagp = fcsr & __excepts; - __rfs(&__fpsr); - *__flagp = __fpsr & __excepts; return (0); } __fenv_static inline int fesetexceptflag(const fexcept_t *__flagp, int __excepts) { - fexcept_t __fpsr; + fexcept_t fcsr; + + __excepts &= FE_ALL_EXCEPT; + __cfc1(fcsr); + fcsr &= ~__excepts; + fcsr |= *__flagp & __excepts; + __ctc1(fcsr); - __rfs(&__fpsr); - __fpsr &= ~__excepts; - __fpsr |= *__flagp & __excepts; - __wfs(__fpsr); return (0); } __fenv_static inline int feraiseexcept(int __excepts) { - fexcept_t __ex = __excepts; + fexcept_t fcsr; + + __excepts &= FE_ALL_EXCEPT; + __cfc1(fcsr); + fcsr |= __excepts | (__excepts << _FCSR_CAUSE_SHIFT); + __ctc1(fcsr); - fesetexceptflag(&__ex, __excepts); /* XXX */ return (0); } __fenv_static inline int fetestexcept(int __excepts) { - fexcept_t __fpsr; + fexcept_t fcsr; - __rfs(&__fpsr); - return (__fpsr & __excepts); + __excepts &= FE_ALL_EXCEPT; + __cfc1(fcsr); + + return (fcsr & __excepts); } __fenv_static inline int fegetround(void) { + fexcept_t fcsr; + + __cfc1(fcsr); - /* - * Apparently, the rounding mode is specified as part of the - * instruction format on ARM, so the dynamic rounding mode is - * indeterminate. Some FPUs may differ. - */ - return (-1); + return (fcsr & _ROUND_MASK); } __fenv_static inline int fesetround(int __round) { + fexcept_t fcsr; + + if (__round & ~_ROUND_MASK) + return (-1); - return (-1); + __cfc1(fcsr); + fcsr &= ~_ROUND_MASK; + fcsr |= __round; + __ctc1(fcsr); + + return (0); } __fenv_static inline int fegetenv(fenv_t *__envp) { - __rfs(__envp); + __cfc1(*__envp); + return (0); } __fenv_static inline int feholdexcept(fenv_t *__envp) { - fenv_t __env; + fexcept_t fcsr; + + __cfc1(fcsr); + *__envp = fcsr; + fcsr &= ~(FE_ALL_EXCEPT | _ENABLE_MASK); + __ctc1(fcsr); - __rfs(&__env); - *__envp = __env; - __env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK); - __wfs(__env); return (0); } @@ -166,56 +207,69 @@ __fenv_static inline int fesetenv(const fenv_t *__envp) { - __wfs(*__envp); + __ctc1(*__envp); + return (0); } __fenv_static inline int feupdateenv(const fenv_t *__envp) { - fexcept_t __fpsr; + fexcept_t fcsr; + + __cfc1(fcsr); + fesetenv(__envp); + feraiseexcept(fcsr); - __rfs(&__fpsr); - __wfs(*__envp); - feraiseexcept(__fpsr & FE_ALL_EXCEPT); return (0); } +#endif /* !SOFTFLOAT */ #if __BSD_VISIBLE /* We currently provide no external definitions of the functions below. */ +#ifdef SOFTFLOAT +int feenableexcept(int __mask); +int fedisableexcept(int __mask); +int fegetexcept(void); +#else static inline int feenableexcept(int __mask) { - fenv_t __old_fpsr, __new_fpsr; + fenv_t __old_fcsr, __new_fcsr; + + __cfc1(__old_fcsr); + __new_fcsr = __old_fcsr | (__mask & FE_ALL_EXCEPT) << _ENABLE_SHIFT; + __ctc1(__new_fcsr); - __rfs(&__old_fpsr); - __new_fpsr = __old_fpsr | (__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT; - __wfs(__new_fpsr); - return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT); + return ((__old_fcsr >> _ENABLE_SHIFT) & FE_ALL_EXCEPT); } static inline int fedisableexcept(int __mask) { - fenv_t __old_fpsr, __new_fpsr; + fenv_t __old_fcsr, __new_fcsr; + + __cfc1(__old_fcsr); + __new_fcsr = __old_fcsr & ~((__mask & FE_ALL_EXCEPT) << _ENABLE_SHIFT); + __ctc1(__new_fcsr); - __rfs(&__old_fpsr); - __new_fpsr = __old_fpsr & ~((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT); - __wfs(__new_fpsr); - return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT); + return ((__old_fcsr >> _ENABLE_SHIFT) & FE_ALL_EXCEPT); } static inline int fegetexcept(void) { - fenv_t __fpsr; + fexcept_t fcsr; - __rfs(&__fpsr); - return ((__fpsr & _ENABLE_MASK) >> _FPUSW_SHIFT); + __cfc1(fcsr); + + return ((fcsr & _ENABLE_MASK) >> _ENABLE_SHIFT); } +#endif /* !SOFTFLOAT */ + #endif /* __BSD_VISIBLE */ __END_DECLS |
