aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRuslan Bukin <br@FreeBSD.org>2016-10-31 15:33:58 +0000
committerRuslan Bukin <br@FreeBSD.org>2016-10-31 15:33:58 +0000
commit5bca221511e448277905383c6c08180e624c7460 (patch)
tree6e8b7ee360ff41786ad352e2b2797425cfbd6255 /lib
parentad9f2cecd74098261d39c1b2a0e85908fa9e122f (diff)
Notes
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/Makefile2
-rw-r--r--lib/libc/mips/Makefile.inc2
-rw-r--r--lib/libc/mips/Symbol.map4
-rw-r--r--lib/libc/mips/gen/Makefile.inc2
-rw-r--r--lib/libc/mips/gen/flt_rounds.c20
-rw-r--r--lib/msun/mips/Makefile.inc4
-rw-r--r--lib/msun/mips/Symbol.map8
-rw-r--r--lib/msun/mips/fenv.c14
-rw-r--r--lib/msun/mips/fenv.h166
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