summaryrefslogtreecommitdiffstats
path: root/libm
diff options
context:
space:
mode:
authorCalin Juravle <calin@google.com>2014-02-25 14:49:41 +0000
committerCalin Juravle <calin@google.com>2014-02-26 12:30:44 +0000
commit2d367905a2e1b950f79b408141eea07c222b590b (patch)
tree8f5d47b3513c213114549acaef2d8f3e6adecd09 /libm
parenta92b57c7f8230661d911f2fd6dd67a81e9a90cef (diff)
downloadbionic-2d367905a2e1b950f79b408141eea07c222b590b.zip
bionic-2d367905a2e1b950f79b408141eea07c222b590b.tar.gz
bionic-2d367905a2e1b950f79b408141eea07c222b590b.tar.bz2
Moved to a more openbsd-like fenv.h
Factored out common declarations to include/fenv.h and pushed the implementation to .c files. Bug: 11050744 Change-Id: I446b13cc4bc599d328343a8d392b07de280f6304
Diffstat (limited to 'libm')
-rwxr-xr-xlibm/amd64/fenv.c340
-rw-r--r--libm/arm/fenv.c103
-rw-r--r--libm/arm64/fenv.c106
-rw-r--r--libm/i387/fenv.c484
-rw-r--r--libm/include/amd64/machine/fenv.h (renamed from libm/include/amd64/fenv.h)99
-rw-r--r--libm/include/arm/fenv.h176
-rw-r--r--libm/include/arm/machine/fenv.h68
-rw-r--r--libm/include/arm64/machine/fenv.h (renamed from libm/include/arm64/fenv.h)127
-rw-r--r--libm/include/fenv.h69
-rw-r--r--libm/include/i387/machine/fenv.h (renamed from libm/include/i387/fenv.h)80
-rw-r--r--libm/include/mips/fenv.h225
-rw-r--r--libm/include/mips/machine/fenv.h105
-rw-r--r--libm/mips/fenv.c115
13 files changed, 1039 insertions, 1058 deletions
diff --git a/libm/amd64/fenv.c b/libm/amd64/fenv.c
index 7ad3be7..b2c017b 100755
--- a/libm/amd64/fenv.c
+++ b/libm/amd64/fenv.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: fenv.c,v 1.3 2012/12/05 23:20:02 deraadt Exp $ */
-/* $NetBSD: fenv.c,v 1.1 2010/07/31 21:47:53 joerg Exp $ */
+/* $OpenBSD: fenv.c,v 1.3 2012/12/05 23:20:02 deraadt Exp $ */
+/* $NetBSD: fenv.c,v 1.1 2010/07/31 21:47:53 joerg Exp $ */
/*-
* Copyright (c) 2004-2005 David Schultz <das (at) FreeBSD.ORG>
@@ -43,18 +43,18 @@
* RESERVED.
*/
fenv_t __fe_dfl_env = {
- {
- 0xffff0000 | __INITIAL_NPXCW__, /* Control word register */
- 0xffff0000, /* Status word register */
- 0xffffffff, /* Tag word register */
- {
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0xffff0000
- }
- },
- __INITIAL_MXCSR__ /* MXCSR register */
+ {
+ 0xffff0000 | __INITIAL_NPXCW__, /* Control word register */
+ 0xffff0000, /* Status word register */
+ 0xffffffff, /* Tag word register */
+ {
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0xffff0000
+ }
+ },
+ __INITIAL_MXCSR__ /* MXCSR register */
};
@@ -65,26 +65,26 @@ fenv_t __fe_dfl_env = {
int
feclearexcept(int excepts)
{
- fenv_t fenv;
- unsigned int mxcsr;
+ fenv_t fenv;
+ unsigned int mxcsr;
- excepts &= FE_ALL_EXCEPT;
+ excepts &= FE_ALL_EXCEPT;
- /* Store the current x87 floating-point environment */
- __asm__ __volatile__ ("fnstenv %0" : "=m" (fenv));
+ /* Store the current x87 floating-point environment */
+ __asm__ __volatile__ ("fnstenv %0" : "=m" (fenv));
- /* Clear the requested floating-point exceptions */
- fenv.__x87.__status &= ~excepts;
+ /* Clear the requested floating-point exceptions */
+ fenv.__x87.__status &= ~excepts;
- /* Load the x87 floating-point environent */
- __asm__ __volatile__ ("fldenv %0" : : "m" (fenv));
+ /* Load the x87 floating-point environent */
+ __asm__ __volatile__ ("fldenv %0" : : "m" (fenv));
- /* Same for SSE environment */
- __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr));
- mxcsr &= ~excepts;
- __asm__ __volatile__ ("ldmxcsr %0" : : "m" (mxcsr));
+ /* Same for SSE environment */
+ __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr));
+ mxcsr &= ~excepts;
+ __asm__ __volatile__ ("ldmxcsr %0" : : "m" (mxcsr));
- return (0);
+ return (0);
}
/*
@@ -95,21 +95,21 @@ feclearexcept(int excepts)
int
fegetexceptflag(fexcept_t *flagp, int excepts)
{
- unsigned short status;
- unsigned int mxcsr;
+ unsigned short status;
+ unsigned int mxcsr;
- excepts &= FE_ALL_EXCEPT;
+ excepts &= FE_ALL_EXCEPT;
- /* Store the current x87 status register */
- __asm__ __volatile__ ("fnstsw %0" : "=am" (status));
+ /* Store the current x87 status register */
+ __asm__ __volatile__ ("fnstsw %0" : "=am" (status));
- /* Store the MXCSR register */
- __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr));
+ /* Store the MXCSR register */
+ __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr));
- /* Store the results in flagp */
- *flagp = (status | mxcsr) & excepts;
+ /* Store the results in flagp */
+ *flagp = (status | mxcsr) & excepts;
- return (0);
+ return (0);
}
/*
@@ -125,12 +125,12 @@ fegetexceptflag(fexcept_t *flagp, int excepts)
int
feraiseexcept(int excepts)
{
- excepts &= FE_ALL_EXCEPT;
+ excepts &= FE_ALL_EXCEPT;
- fesetexceptflag((fexcept_t *)&excepts, excepts);
- __asm__ __volatile__ ("fwait");
+ fesetexceptflag((fexcept_t *)&excepts, excepts);
+ __asm__ __volatile__ ("fwait");
- return (0);
+ return (0);
}
/*
@@ -141,28 +141,28 @@ feraiseexcept(int excepts)
int
fesetexceptflag(const fexcept_t *flagp, int excepts)
{
- fenv_t fenv;
- unsigned int mxcsr;
+ fenv_t fenv;
+ unsigned int mxcsr;
- excepts &= FE_ALL_EXCEPT;
+ excepts &= FE_ALL_EXCEPT;
- /* Store the current x87 floating-point environment */
- __asm__ __volatile__ ("fnstenv %0" : "=m" (fenv));
+ /* Store the current x87 floating-point environment */
+ __asm__ __volatile__ ("fnstenv %0" : "=m" (fenv));
- /* Set the requested status flags */
- fenv.__x87.__status &= ~excepts;
- fenv.__x87.__status |= *flagp & excepts;
+ /* Set the requested status flags */
+ fenv.__x87.__status &= ~excepts;
+ fenv.__x87.__status |= *flagp & excepts;
- /* Load the x87 floating-point environent */
- __asm__ __volatile__ ("fldenv %0" : : "m" (fenv));
+ /* Load the x87 floating-point environent */
+ __asm__ __volatile__ ("fldenv %0" : : "m" (fenv));
- /* Same for SSE environment */
- __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr));
- mxcsr &= ~excepts;
- mxcsr |= *flagp & excepts;
- __asm__ __volatile__ ("ldmxcsr %0" : : "m" (mxcsr));
+ /* Same for SSE environment */
+ __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr));
+ mxcsr &= ~excepts;
+ mxcsr |= *flagp & excepts;
+ __asm__ __volatile__ ("ldmxcsr %0" : : "m" (mxcsr));
- return (0);
+ return (0);
}
/*
@@ -173,18 +173,18 @@ fesetexceptflag(const fexcept_t *flagp, int excepts)
int
fetestexcept(int excepts)
{
- unsigned short status;
- unsigned int mxcsr;
+ unsigned short status;
+ unsigned int mxcsr;
- excepts &= FE_ALL_EXCEPT;
+ excepts &= FE_ALL_EXCEPT;
- /* Store the current x87 status register */
- __asm__ __volatile__ ("fnstsw %0" : "=am" (status));
+ /* Store the current x87 status register */
+ __asm__ __volatile__ ("fnstsw %0" : "=am" (status));
- /* Store the MXCSR register state */
- __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr));
+ /* Store the MXCSR register state */
+ __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr));
- return ((status | mxcsr) & excepts);
+ return ((status | mxcsr) & excepts);
}
/*
@@ -193,17 +193,17 @@ fetestexcept(int excepts)
int
fegetround(void)
{
- unsigned short control;
+ unsigned short control;
- /*
- * We assume that the x87 and the SSE unit agree on the
- * rounding mode. Reading the control word on the x87 turns
- * out to be about 5 times faster than reading it on the SSE
- * unit on an Opteron 244.
- */
- __asm__ __volatile__ ("fnstcw %0" : "=m" (control));
+ /*
+ * We assume that the x87 and the SSE unit agree on the
+ * rounding mode. Reading the control word on the x87 turns
+ * out to be about 5 times faster than reading it on the SSE
+ * unit on an Opteron 244.
+ */
+ __asm__ __volatile__ ("fnstcw %0" : "=m" (control));
- return (control & _X87_ROUND_MASK);
+ return (control & _X87_ROUND_MASK);
}
/*
@@ -214,30 +214,30 @@ fegetround(void)
int
fesetround(int round)
{
- unsigned short control;
- unsigned int mxcsr;
+ unsigned short control;
+ unsigned int mxcsr;
- /* Check whether requested rounding direction is supported */
- if (round & ~_X87_ROUND_MASK)
- return (-1);
+ /* Check whether requested rounding direction is supported */
+ if (round & ~_X87_ROUND_MASK)
+ return (-1);
- /* Store the current x87 control word register */
- __asm__ __volatile__ ("fnstcw %0" : "=m" (control));
+ /* Store the current x87 control word register */
+ __asm__ __volatile__ ("fnstcw %0" : "=m" (control));
- /* Set the rounding direction */
- control &= ~_X87_ROUND_MASK;
- control |= round;
+ /* Set the rounding direction */
+ control &= ~_X87_ROUND_MASK;
+ control |= round;
- /* Load the x87 control word register */
- __asm__ __volatile__ ("fldcw %0" : : "m" (control));
+ /* Load the x87 control word register */
+ __asm__ __volatile__ ("fldcw %0" : : "m" (control));
- /* Same for the SSE environment */
- __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr));
- mxcsr &= ~(_X87_ROUND_MASK << _SSE_ROUND_SHIFT);
- mxcsr |= round << _SSE_ROUND_SHIFT;
- __asm__ __volatile__ ("ldmxcsr %0" : : "m" (mxcsr));
+ /* Same for the SSE environment */
+ __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr));
+ mxcsr &= ~(_X87_ROUND_MASK << _SSE_ROUND_SHIFT);
+ mxcsr |= round << _SSE_ROUND_SHIFT;
+ __asm__ __volatile__ ("ldmxcsr %0" : : "m" (mxcsr));
- return (0);
+ return (0);
}
/*
@@ -247,23 +247,23 @@ fesetround(int round)
int
fegetenv(fenv_t *envp)
{
- /* Store the current x87 floating-point environment */
- __asm__ __volatile__ ("fnstenv %0" : "=m" (*envp));
-
- /* Store the MXCSR register state */
- __asm__ __volatile__ ("stmxcsr %0" : "=m" (envp->__mxcsr));
-
- /*
- * When an FNSTENV instruction is executed, all pending exceptions are
- * essentially lost (either the x87 FPU status register is cleared or
- * all exceptions are masked).
- *
- * 8.6 X87 FPU EXCEPTION SYNCHRONIZATION -
- * Intel(R) 64 and IA-32 Architectures Softare Developer's Manual - Vol1
- */
- __asm__ __volatile__ ("fldcw %0" : : "m" (envp->__x87.__control));
-
- return (0);
+ /* Store the current x87 floating-point environment */
+ __asm__ __volatile__ ("fnstenv %0" : "=m" (*envp));
+
+ /* Store the MXCSR register state */
+ __asm__ __volatile__ ("stmxcsr %0" : "=m" (envp->__mxcsr));
+
+ /*
+ * When an FNSTENV instruction is executed, all pending exceptions are
+ * essentially lost (either the x87 FPU status register is cleared or
+ * all exceptions are masked).
+ *
+ * 8.6 X87 FPU EXCEPTION SYNCHRONIZATION -
+ * Intel(R) 64 and IA-32 Architectures Softare Developer's Manual - Vol1
+ */
+ __asm__ __volatile__ ("fldcw %0" : : "m" (envp->__x87.__control));
+
+ return (0);
}
/*
@@ -275,28 +275,28 @@ fegetenv(fenv_t *envp)
int
feholdexcept(fenv_t *envp)
{
- unsigned int mxcsr;
+ unsigned int mxcsr;
- /* Store the current x87 floating-point environment */
- __asm__ __volatile__ ("fnstenv %0" : "=m" (*envp));
+ /* Store the current x87 floating-point environment */
+ __asm__ __volatile__ ("fnstenv %0" : "=m" (*envp));
- /* Clear all exception flags in FPU */
- __asm__ __volatile__ ("fnclex");
+ /* Clear all exception flags in FPU */
+ __asm__ __volatile__ ("fnclex");
- /* Store the MXCSR register state */
- __asm__ __volatile__ ("stmxcsr %0" : "=m" (envp->__mxcsr));
+ /* Store the MXCSR register state */
+ __asm__ __volatile__ ("stmxcsr %0" : "=m" (envp->__mxcsr));
- /* Clear exception flags in MXCSR */
- mxcsr = envp->__mxcsr;
- mxcsr &= ~FE_ALL_EXCEPT;
+ /* Clear exception flags in MXCSR */
+ mxcsr = envp->__mxcsr;
+ mxcsr &= ~FE_ALL_EXCEPT;
- /* Mask all exceptions */
- mxcsr |= FE_ALL_EXCEPT << _SSE_MASK_SHIFT;
+ /* Mask all exceptions */
+ mxcsr |= FE_ALL_EXCEPT << _SSE_MASK_SHIFT;
- /* Store the MXCSR register */
- __asm__ __volatile__ ("ldmxcsr %0" : : "m" (mxcsr));
+ /* Store the MXCSR register */
+ __asm__ __volatile__ ("ldmxcsr %0" : : "m" (mxcsr));
- return (0);
+ return (0);
}
/*
@@ -310,13 +310,13 @@ feholdexcept(fenv_t *envp)
int
fesetenv(const fenv_t *envp)
{
- /* Load the x87 floating-point environent */
- __asm__ __volatile__ ("fldenv %0" : : "m" (*envp));
+ /* Load the x87 floating-point environent */
+ __asm__ __volatile__ ("fldenv %0" : : "m" (*envp));
- /* Store the MXCSR register */
- __asm__ __volatile__ ("ldmxcsr %0" : : "m" (envp->__mxcsr));
+ /* Store the MXCSR register */
+ __asm__ __volatile__ ("ldmxcsr %0" : : "m" (envp->__mxcsr));
- return (0);
+ return (0);
}
/*
@@ -330,22 +330,22 @@ fesetenv(const fenv_t *envp)
int
feupdateenv(const fenv_t *envp)
{
- unsigned short status;
- unsigned int mxcsr;
+ unsigned short status;
+ unsigned int mxcsr;
- /* Store the x87 status register */
- __asm__ __volatile__ ("fnstsw %0" : "=am" (status));
+ /* Store the x87 status register */
+ __asm__ __volatile__ ("fnstsw %0" : "=am" (status));
- /* Store the MXCSR register */
- __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr));
+ /* Store the MXCSR register */
+ __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr));
- /* Install new floating-point environment */
- fesetenv(envp);
+ /* Install new floating-point environment */
+ fesetenv(envp);
- /* Raise any previously accumulated exceptions */
- feraiseexcept(status | mxcsr);
+ /* Raise any previously accumulated exceptions */
+ feraiseexcept(status | mxcsr);
- return (0);
+ return (0);
}
/*
@@ -354,55 +354,55 @@ feupdateenv(const fenv_t *envp)
int
feenableexcept(int mask)
{
- unsigned int mxcsr, omask;
- unsigned short control;
+ unsigned int mxcsr, omask;
+ unsigned short control;
- mask &= FE_ALL_EXCEPT;
+ mask &= FE_ALL_EXCEPT;
- __asm__ __volatile__ ("fnstcw %0" : "=m" (control));
- __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr));
+ __asm__ __volatile__ ("fnstcw %0" : "=m" (control));
+ __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr));
- omask = ~(control | (mxcsr >> _SSE_MASK_SHIFT)) & FE_ALL_EXCEPT;
- control &= ~mask;
- __asm__ __volatile__ ("fldcw %0" : : "m" (control));
+ omask = ~(control | (mxcsr >> _SSE_MASK_SHIFT)) & FE_ALL_EXCEPT;
+ control &= ~mask;
+ __asm__ __volatile__ ("fldcw %0" : : "m" (control));
- mxcsr &= ~(mask << _SSE_MASK_SHIFT);
- __asm__ __volatile__ ("ldmxcsr %0" : : "m" (mxcsr));
+ mxcsr &= ~(mask << _SSE_MASK_SHIFT);
+ __asm__ __volatile__ ("ldmxcsr %0" : : "m" (mxcsr));
- return (omask);
+ return (omask);
}
int
fedisableexcept(int mask)
{
- unsigned int mxcsr, omask;
- unsigned short control;
+ unsigned int mxcsr, omask;
+ unsigned short control;
- mask &= FE_ALL_EXCEPT;
+ mask &= FE_ALL_EXCEPT;
- __asm__ __volatile__ ("fnstcw %0" : "=m" (control));
- __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr));
+ __asm__ __volatile__ ("fnstcw %0" : "=m" (control));
+ __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr));
- omask = ~(control | (mxcsr >> _SSE_MASK_SHIFT)) & FE_ALL_EXCEPT;
- control |= mask;
- __asm__ __volatile__ ("fldcw %0" : : "m" (control));
+ omask = ~(control | (mxcsr >> _SSE_MASK_SHIFT)) & FE_ALL_EXCEPT;
+ control |= mask;
+ __asm__ __volatile__ ("fldcw %0" : : "m" (control));
- mxcsr |= mask << _SSE_MASK_SHIFT;
- __asm__ __volatile__ ("ldmxcsr %0" : : "m" (mxcsr));
+ mxcsr |= mask << _SSE_MASK_SHIFT;
+ __asm__ __volatile__ ("ldmxcsr %0" : : "m" (mxcsr));
- return (omask);
+ return (omask);
}
int
fegetexcept(void)
{
- unsigned short control;
+ unsigned short control;
- /*
- * We assume that the masks for the x87 and the SSE unit are
- * the same.
- */
- __asm__ __volatile__ ("fnstcw %0" : "=m" (control));
+ /*
+ * We assume that the masks for the x87 and the SSE unit are
+ * the same.
+ */
+ __asm__ __volatile__ ("fnstcw %0" : "=m" (control));
- return (~control & FE_ALL_EXCEPT);
+ return (~control & FE_ALL_EXCEPT);
}
diff --git a/libm/arm/fenv.c b/libm/arm/fenv.c
index 469f198..a0108e8 100644
--- a/libm/arm/fenv.c
+++ b/libm/arm/fenv.c
@@ -33,3 +33,106 @@
* this as a default environment.
*/
const fenv_t __fe_dfl_env = 0;
+
+int fegetenv(fenv_t* __envp) {
+ fenv_t _fpscr;
+ __asm__ __volatile__("vmrs %0,fpscr" : "=r" (_fpscr));
+ *__envp = _fpscr;
+ return 0;
+}
+
+int fesetenv(const fenv_t* __envp) {
+ fenv_t _fpscr = *__envp;
+ __asm__ __volatile__("vmsr fpscr,%0" : :"ri" (_fpscr));
+ return 0;
+}
+
+int feclearexcept(int __excepts) {
+ fexcept_t __fpscr;
+ fegetenv(&__fpscr);
+ __fpscr &= ~__excepts;
+ fesetenv(&__fpscr);
+ return 0;
+}
+
+int fegetexceptflag(fexcept_t* __flagp, int __excepts) {
+ fexcept_t __fpscr;
+ fegetenv(&__fpscr);
+ *__flagp = __fpscr & __excepts;
+ return 0;
+}
+
+int fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
+ fexcept_t __fpscr;
+ fegetenv(&__fpscr);
+ __fpscr &= ~__excepts;
+ __fpscr |= *__flagp & __excepts;
+ fesetenv(&__fpscr);
+ return 0;
+}
+
+int feraiseexcept(int __excepts) {
+ fexcept_t __ex = __excepts;
+ fesetexceptflag(&__ex, __excepts);
+ return 0;
+}
+
+int fetestexcept(int __excepts) {
+ fexcept_t __fpscr;
+ fegetenv(&__fpscr);
+ return (__fpscr & __excepts);
+}
+
+int fegetround(void) {
+ fenv_t _fpscr;
+ fegetenv(&_fpscr);
+ return ((_fpscr >> _FPSCR_RMODE_SHIFT) & 0x3);
+}
+
+int fesetround(int __round) {
+ fenv_t _fpscr;
+ fegetenv(&_fpscr);
+ _fpscr &= ~(0x3 << _FPSCR_RMODE_SHIFT);
+ _fpscr |= (__round << _FPSCR_RMODE_SHIFT);
+ fesetenv(&_fpscr);
+ return 0;
+}
+
+int feholdexcept(fenv_t* __envp) {
+ fenv_t __env;
+ fegetenv(&__env);
+ *__envp = __env;
+ __env &= ~(FE_ALL_EXCEPT | _FPSCR_ENABLE_MASK);
+ fesetenv(&__env);
+ return 0;
+}
+
+int feupdateenv(const fenv_t* __envp) {
+ fexcept_t __fpscr;
+ fegetenv(&__fpscr);
+ fesetenv(__envp);
+ feraiseexcept(__fpscr & FE_ALL_EXCEPT);
+ return 0;
+}
+
+int feenableexcept(int __mask) {
+ fenv_t __old_fpscr, __new_fpscr;
+ fegetenv(&__old_fpscr);
+ __new_fpscr = __old_fpscr | (__mask & FE_ALL_EXCEPT) << _FPSCR_ENABLE_SHIFT;
+ fesetenv(&__new_fpscr);
+ return ((__old_fpscr >> _FPSCR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
+}
+
+int fedisableexcept(int __mask) {
+ fenv_t __old_fpscr, __new_fpscr;
+ fegetenv(&__old_fpscr);
+ __new_fpscr = __old_fpscr & ~((__mask & FE_ALL_EXCEPT) << _FPSCR_ENABLE_SHIFT);
+ fesetenv(&__new_fpscr);
+ return ((__old_fpscr >> _FPSCR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
+}
+
+int fegetexcept(void) {
+ fenv_t __fpscr;
+ fegetenv(&__fpscr);
+ return ((__fpscr & _FPSCR_ENABLE_MASK) >> _FPSCR_ENABLE_SHIFT);
+}
diff --git a/libm/arm64/fenv.c b/libm/arm64/fenv.c
index 27c405f..9db21ef 100644
--- a/libm/arm64/fenv.c
+++ b/libm/arm64/fenv.c
@@ -33,3 +33,109 @@
* this as a default environment.
*/
const fenv_t __fe_dfl_env = 0;
+
+int fegetenv(fenv_t* __envp) {
+ fenv_t _fpcr, _fpsr;
+ __asm__ __volatile__("mrs %0,fpcr" : "=r" (_fpcr));
+ __asm__ __volatile__("mrs %0,fpsr" : "=r" (_fpsr));
+ *__envp = (_fpcr | _fpsr);
+ return 0;
+}
+
+int fesetenv(const fenv_t* __envp) {
+ fenv_t _fpcr = (*__envp & FPCR_MASK);
+ fenv_t _fpsr = (*__envp & FPSR_MASK);
+ __asm__ __volatile__("msr fpcr,%0" : :"ri" (_fpcr));
+ __asm__ __volatile__("msr fpsr,%0" : :"ri" (_fpsr));
+ return 0;
+}
+
+int feclearexcept(int __excepts) {
+ fexcept_t __fpscr;
+ fegetenv(&__fpscr);
+ __fpscr &= ~__excepts;
+ fesetenv(&__fpscr);
+ return 0;
+}
+
+int fegetexceptflag(fexcept_t* __flagp, int __excepts) {
+ fexcept_t __fpscr;
+ fegetenv(&__fpscr);
+ *__flagp = __fpscr & __excepts;
+ return 0;
+}
+
+int fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
+ fexcept_t __fpscr;
+ fegetenv(&__fpscr);
+ __fpscr &= ~__excepts;
+ __fpscr |= *__flagp & __excepts;
+ fesetenv(&__fpscr);
+ return 0;
+}
+
+int feraiseexcept(int __excepts) {
+ fexcept_t __ex = __excepts;
+ fesetexceptflag(&__ex, __excepts);
+ return 0;
+}
+
+int fetestexcept(int __excepts) {
+ fexcept_t __fpscr;
+ fegetenv(&__fpscr);
+ return (__fpscr & __excepts);
+}
+
+int fegetround(void) {
+ fenv_t _fpscr;
+ fegetenv(&_fpscr);
+ return ((_fpscr >> _FPSCR_RMODE_SHIFT) & 0x3);
+}
+
+int fesetround(int __round) {
+ fenv_t _fpscr;
+ fegetenv(&_fpscr);
+ _fpscr &= ~(0x3 << _FPSCR_RMODE_SHIFT);
+ _fpscr |= (__round << _FPSCR_RMODE_SHIFT);
+ fesetenv(&_fpscr);
+ return 0;
+}
+
+int feholdexcept(fenv_t* __envp) {
+ fenv_t __env;
+ fegetenv(&__env);
+ *__envp = __env;
+ __env &= ~(FE_ALL_EXCEPT | _FPSCR_ENABLE_MASK);
+ fesetenv(&__env);
+ return 0;
+}
+
+int feupdateenv(const fenv_t* __envp) {
+ fexcept_t __fpscr;
+ fegetenv(&__fpscr);
+ fesetenv(__envp);
+ feraiseexcept(__fpscr & FE_ALL_EXCEPT);
+ return 0;
+}
+
+int feenableexcept(int __mask) {
+ fenv_t __old_fpscr, __new_fpscr;
+ fegetenv(&__old_fpscr);
+ __new_fpscr = __old_fpscr | (__mask & FE_ALL_EXCEPT) << _FPSCR_ENABLE_SHIFT;
+ fesetenv(&__new_fpscr);
+ return ((__old_fpscr >> _FPSCR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
+}
+
+int fedisableexcept(int __mask) {
+ fenv_t __old_fpscr, __new_fpscr;
+ fegetenv(&__old_fpscr);
+ __new_fpscr = __old_fpscr & ~((__mask & FE_ALL_EXCEPT) << _FPSCR_ENABLE_SHIFT);
+ fesetenv(&__new_fpscr);
+ return ((__old_fpscr >> _FPSCR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
+}
+
+int fegetexcept(void) {
+ fenv_t __fpscr;
+ fegetenv(&__fpscr);
+ return ((__fpscr & _FPSCR_ENABLE_MASK) >> _FPSCR_ENABLE_SHIFT);
+}
diff --git a/libm/i387/fenv.c b/libm/i387/fenv.c
index 89ddc55..3ab9c58 100644
--- a/libm/i387/fenv.c
+++ b/libm/i387/fenv.c
@@ -36,24 +36,24 @@
* has the rounding control bits offset by 3 and the exception mask
* bits offset by 7.
*/
-#define _SSE_ROUND_SHIFT 3
-#define _SSE_EMASK_SHIFT 7
+#define _SSE_ROUND_SHIFT 3
+#define _SSE_EMASK_SHIFT 7
const fenv_t __fe_dfl_env = {
- __INITIAL_NPXCW__, /*__control*/
- 0x0000, /*__mxcsr_hi*/
- 0x0000, /*__status*/
- 0x1f80, /*__mxcsr_lo*/
- 0xffffffff, /*__tag*/
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff } /*__other*/
+ __INITIAL_NPXCW__, /*__control*/
+ 0x0000, /*__mxcsr_hi*/
+ 0x0000, /*__status*/
+ 0x1f80, /*__mxcsr_lo*/
+ 0xffffffff, /*__tag*/
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff } /*__other*/
};
#define __fldcw(__cw) __asm __volatile("fldcw %0" : : "m" (__cw))
#define __fldenv(__env) __asm __volatile("fldenv %0" : : "m" (__env))
-#define __fldenvx(__env) __asm __volatile("fldenv %0" : : "m" (__env) \
- : "st", "st(1)", "st(2)", "st(3)", "st(4)", \
- "st(5)", "st(6)", "st(7)")
+#define __fldenvx(__env) __asm __volatile("fldenv %0" : : "m" (__env) \
+ : "st", "st(1)", "st(2)", "st(3)", "st(4)", \
+ "st(5)", "st(6)", "st(7)")
#define __fnclex() __asm __volatile("fnclex")
#define __fnstenv(__env) __asm __volatile("fnstenv %0" : "=m" (*(__env)))
#define __fnstcw(__cw) __asm __volatile("fnstcw %0" : "=m" (*(__cw)))
@@ -68,22 +68,22 @@ enum __sse_support { __SSE_YES, __SSE_NO, __SSE_UNK };
#define __HAS_SSE() 1
#else
#define __HAS_SSE() (__has_sse == __SSE_YES || \
- (__has_sse == __SSE_UNK && __test_sse()))
+ (__has_sse == __SSE_UNK && __test_sse()))
#endif
enum __sse_support __has_sse =
#ifdef __SSE__
- __SSE_YES;
+ __SSE_YES;
#else
- __SSE_UNK;
+ __SSE_UNK;
#endif
#ifndef __SSE__
-#define getfl(x) __asm __volatile("pushfl\n\tpopl %0" : "=mr" (*(x)))
-#define setfl(x) __asm __volatile("pushl %0\n\tpopfl" : : "g" (x))
-#define cpuid_dx(x) __asm __volatile("pushl %%ebx\n\tmovl $1, %%eax\n\t" \
- "cpuid\n\tpopl %%ebx" \
- : "=d" (*(x)) : : "eax", "ecx")
+#define getfl(x) __asm __volatile("pushfl\n\tpopl %0" : "=mr" (*(x)))
+#define setfl(x) __asm __volatile("pushl %0\n\tpopfl" : : "g" (x))
+#define cpuid_dx(x) __asm __volatile("pushl %%ebx\n\tmovl $1, %%eax\n\t" \
+ "cpuid\n\tpopl %%ebx" \
+ : "=d" (*(x)) : : "eax", "ecx")
/*
* Test for SSE support on this processor. We need to do this because
@@ -94,298 +94,298 @@ enum __sse_support __has_sse =
int
__test_sse(void)
{
- int flag, nflag;
- int dx_features;
-
- /* Am I a 486? */
- getfl(&flag);
- nflag = flag ^ 0x200000;
- setfl(nflag);
- getfl(&nflag);
- if (flag != nflag) {
- /* Not a 486, so CPUID should work. */
- cpuid_dx(&dx_features);
- if (dx_features & 0x2000000) {
- __has_sse = __SSE_YES;
- return (1);
- }
- }
- __has_sse = __SSE_NO;
- return (0);
+ int flag, nflag;
+ int dx_features;
+
+ /* Am I a 486? */
+ getfl(&flag);
+ nflag = flag ^ 0x200000;
+ setfl(nflag);
+ getfl(&nflag);
+ if (flag != nflag) {
+ /* Not a 486, so CPUID should work. */
+ cpuid_dx(&dx_features);
+ if (dx_features & 0x2000000) {
+ __has_sse = __SSE_YES;
+ return (1);
+ }
+ }
+ __has_sse = __SSE_NO;
+ return (0);
}
#endif /* __SSE__ */
int
fesetexceptflag(const fexcept_t *flagp, int excepts)
{
- fenv_t env;
- __uint32_t mxcsr;
-
- excepts &= FE_ALL_EXCEPT;
- if (excepts) { /* Do nothing if excepts is 0 */
- __fnstenv(&env);
- env.__status &= ~excepts;
- env.__status |= *flagp & excepts;
- __fnclex();
- __fldenv(env);
- if (__HAS_SSE()) {
- __stmxcsr(&mxcsr);
- mxcsr &= ~excepts;
- mxcsr |= *flagp & excepts;
- __ldmxcsr(mxcsr);
- }
- }
-
- return (0);
+ fenv_t env;
+ __uint32_t mxcsr;
+
+ excepts &= FE_ALL_EXCEPT;
+ if (excepts) { /* Do nothing if excepts is 0 */
+ __fnstenv(&env);
+ env.__status &= ~excepts;
+ env.__status |= *flagp & excepts;
+ __fnclex();
+ __fldenv(env);
+ if (__HAS_SSE()) {
+ __stmxcsr(&mxcsr);
+ mxcsr &= ~excepts;
+ mxcsr |= *flagp & excepts;
+ __ldmxcsr(mxcsr);
+ }
+ }
+
+ return (0);
}
int
feraiseexcept(int excepts)
{
- fexcept_t ex = excepts;
+ fexcept_t ex = excepts;
- fesetexceptflag(&ex, excepts);
- __fwait();
- return (0);
+ fesetexceptflag(&ex, excepts);
+ __fwait();
+ return (0);
}
int
fegetenv(fenv_t *envp)
{
- __uint32_t mxcsr;
-
- __fnstenv(envp);
- /*
- * fnstenv masks all exceptions, so we need to restore
- * the old control word to avoid this side effect.
- */
- __fldcw(envp->__control);
- if (__HAS_SSE()) {
- __stmxcsr(&mxcsr);
- envp->__mxcsr_hi = mxcsr >> 16;
- envp->__mxcsr_lo = mxcsr & 0xffff;
- }
- return (0);
+ __uint32_t mxcsr;
+
+ __fnstenv(envp);
+ /*
+ * fnstenv masks all exceptions, so we need to restore
+ * the old control word to avoid this side effect.
+ */
+ __fldcw(envp->__control);
+ if (__HAS_SSE()) {
+ __stmxcsr(&mxcsr);
+ envp->__mxcsr_hi = mxcsr >> 16;
+ envp->__mxcsr_lo = mxcsr & 0xffff;
+ }
+ return (0);
}
int
feholdexcept(fenv_t *envp)
{
- __uint32_t mxcsr;
- fenv_t env;
-
- __fnstenv(&env);
- *envp = env;
- env.__status &= ~FE_ALL_EXCEPT;
- env.__control |= FE_ALL_EXCEPT;
- __fnclex();
- __fldenv(env);
- if (__HAS_SSE()) {
- __stmxcsr(&mxcsr);
- envp->__mxcsr_hi = mxcsr >> 16;
- envp->__mxcsr_lo = mxcsr & 0xffff;
- mxcsr &= ~FE_ALL_EXCEPT;
- mxcsr |= FE_ALL_EXCEPT << _SSE_EMASK_SHIFT;
- __ldmxcsr(mxcsr);
- }
- return (0);
+ __uint32_t mxcsr;
+ fenv_t env;
+
+ __fnstenv(&env);
+ *envp = env;
+ env.__status &= ~FE_ALL_EXCEPT;
+ env.__control |= FE_ALL_EXCEPT;
+ __fnclex();
+ __fldenv(env);
+ if (__HAS_SSE()) {
+ __stmxcsr(&mxcsr);
+ envp->__mxcsr_hi = mxcsr >> 16;
+ envp->__mxcsr_lo = mxcsr & 0xffff;
+ mxcsr &= ~FE_ALL_EXCEPT;
+ mxcsr |= FE_ALL_EXCEPT << _SSE_EMASK_SHIFT;
+ __ldmxcsr(mxcsr);
+ }
+ return (0);
}
int
feupdateenv(const fenv_t *envp)
{
- __uint32_t mxcsr;
- __uint16_t status;
-
- __fnstsw(&status);
- if (__HAS_SSE()) {
- __stmxcsr(&mxcsr);
- } else {
- mxcsr = 0;
- }
- fesetenv(envp);
- feraiseexcept((mxcsr | status) & FE_ALL_EXCEPT);
- return (0);
+ __uint32_t mxcsr;
+ __uint16_t status;
+
+ __fnstsw(&status);
+ if (__HAS_SSE()) {
+ __stmxcsr(&mxcsr);
+ } else {
+ mxcsr = 0;
+ }
+ fesetenv(envp);
+ feraiseexcept((mxcsr | status) & FE_ALL_EXCEPT);
+ return (0);
}
int
feenableexcept(int mask)
{
- __uint32_t mxcsr;
- __uint16_t control, omask;
-
- mask &= FE_ALL_EXCEPT;
- __fnstcw(&control);
- if (__HAS_SSE()) {
- __stmxcsr(&mxcsr);
- } else {
- mxcsr = 0;
- }
- omask = ~(control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT;
- if (mask) {
- control &= ~mask;
- __fldcw(control);
- if (__HAS_SSE()) {
- mxcsr &= ~(mask << _SSE_EMASK_SHIFT);
- __ldmxcsr(mxcsr);
- }
- }
- return (omask);
+ __uint32_t mxcsr;
+ __uint16_t control, omask;
+
+ mask &= FE_ALL_EXCEPT;
+ __fnstcw(&control);
+ if (__HAS_SSE()) {
+ __stmxcsr(&mxcsr);
+ } else {
+ mxcsr = 0;
+ }
+ omask = ~(control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT;
+ if (mask) {
+ control &= ~mask;
+ __fldcw(control);
+ if (__HAS_SSE()) {
+ mxcsr &= ~(mask << _SSE_EMASK_SHIFT);
+ __ldmxcsr(mxcsr);
+ }
+ }
+ return (omask);
}
int
fedisableexcept(int mask)
{
- __uint32_t mxcsr;
- __uint16_t control, omask;
-
- mask &= FE_ALL_EXCEPT;
- __fnstcw(&control);
- if (__HAS_SSE()) {
- __stmxcsr(&mxcsr);
- } else {
- mxcsr = 0;
- }
- omask = ~(control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT;
- if (mask) {
- control |= mask;
- __fldcw(control);
- if (__HAS_SSE()) {
- mxcsr |= mask << _SSE_EMASK_SHIFT;
- __ldmxcsr(mxcsr);
- }
- }
- return (omask);
+ __uint32_t mxcsr;
+ __uint16_t control, omask;
+
+ mask &= FE_ALL_EXCEPT;
+ __fnstcw(&control);
+ if (__HAS_SSE()) {
+ __stmxcsr(&mxcsr);
+ } else {
+ mxcsr = 0;
+ }
+ omask = ~(control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT;
+ if (mask) {
+ control |= mask;
+ __fldcw(control);
+ if (__HAS_SSE()) {
+ mxcsr |= mask << _SSE_EMASK_SHIFT;
+ __ldmxcsr(mxcsr);
+ }
+ }
+ return (omask);
}
int
feclearexcept(int excepts)
{
- fenv_t env;
- __uint32_t mxcsr;
-
- excepts &= FE_ALL_EXCEPT;
- if (excepts) { /* Do nothing if excepts is 0 */
- __fnstenv(&env);
- env.__status &= ~excepts;
- __fnclex();
- __fldenv(env);
- if (__HAS_SSE()) {
- __stmxcsr(&mxcsr);
- mxcsr &= ~excepts;
- __ldmxcsr(mxcsr);
- }
- }
- return (0);
+ fenv_t env;
+ __uint32_t mxcsr;
+
+ excepts &= FE_ALL_EXCEPT;
+ if (excepts) { /* Do nothing if excepts is 0 */
+ __fnstenv(&env);
+ env.__status &= ~excepts;
+ __fnclex();
+ __fldenv(env);
+ if (__HAS_SSE()) {
+ __stmxcsr(&mxcsr);
+ mxcsr &= ~excepts;
+ __ldmxcsr(mxcsr);
+ }
+ }
+ return (0);
}
int
fegetexceptflag(fexcept_t *flagp, int excepts)
{
- __uint32_t mxcsr;
- __uint16_t status;
-
- excepts &= FE_ALL_EXCEPT;
- __fnstsw(&status);
- if (__HAS_SSE()) {
- __stmxcsr(&mxcsr);
- } else {
- mxcsr = 0;
- }
- *flagp = (status | mxcsr) & excepts;
- return (0);
+ __uint32_t mxcsr;
+ __uint16_t status;
+
+ excepts &= FE_ALL_EXCEPT;
+ __fnstsw(&status);
+ if (__HAS_SSE()) {
+ __stmxcsr(&mxcsr);
+ } else {
+ mxcsr = 0;
+ }
+ *flagp = (status | mxcsr) & excepts;
+ return (0);
}
int
fetestexcept(int excepts)
{
- __uint32_t mxcsr;
- __uint16_t status;
-
- excepts &= FE_ALL_EXCEPT;
- if (excepts) { /* Do nothing if excepts is 0 */
- __fnstsw(&status);
- if (__HAS_SSE()) {
- __stmxcsr(&mxcsr);
- } else {
- mxcsr = 0;
- }
- return ((status | mxcsr) & excepts);
- }
- return (0);
+ __uint32_t mxcsr;
+ __uint16_t status;
+
+ excepts &= FE_ALL_EXCEPT;
+ if (excepts) { /* Do nothing if excepts is 0 */
+ __fnstsw(&status);
+ if (__HAS_SSE()) {
+ __stmxcsr(&mxcsr);
+ } else {
+ mxcsr = 0;
+ }
+ return ((status | mxcsr) & excepts);
+ }
+ return (0);
}
int
fegetround(void)
{
- __uint16_t control;
-
- /*
- * We assume that the x87 and the SSE unit agree on the
- * rounding mode. Reading the control word on the x87 turns
- * out to be about 5 times faster than reading it on the SSE
- * unit on an Opteron 244.
- */
- __fnstcw(&control);
- return (control & _ROUND_MASK);
+ __uint16_t control;
+
+ /*
+ * We assume that the x87 and the SSE unit agree on the
+ * rounding mode. Reading the control word on the x87 turns
+ * out to be about 5 times faster than reading it on the SSE
+ * unit on an Opteron 244.
+ */
+ __fnstcw(&control);
+ return (control & _ROUND_MASK);
}
int
fesetround(int round)
{
- __uint32_t mxcsr;
- __uint16_t control;
-
- if (round & ~_ROUND_MASK) {
- return (-1);
- } else {
- __fnstcw(&control);
- control &= ~_ROUND_MASK;
- control |= round;
- __fldcw(control);
- if (__HAS_SSE()) {
- __stmxcsr(&mxcsr);
- mxcsr &= ~(_ROUND_MASK << _SSE_ROUND_SHIFT);
- mxcsr |= round << _SSE_ROUND_SHIFT;
- __ldmxcsr(mxcsr);
- }
- return (0);
- }
+ __uint32_t mxcsr;
+ __uint16_t control;
+
+ if (round & ~_ROUND_MASK) {
+ return (-1);
+ } else {
+ __fnstcw(&control);
+ control &= ~_ROUND_MASK;
+ control |= round;
+ __fldcw(control);
+ if (__HAS_SSE()) {
+ __stmxcsr(&mxcsr);
+ mxcsr &= ~(_ROUND_MASK << _SSE_ROUND_SHIFT);
+ mxcsr |= round << _SSE_ROUND_SHIFT;
+ __ldmxcsr(mxcsr);
+ }
+ return (0);
+ }
}
int
fesetenv(const fenv_t *envp)
{
- fenv_t env = *envp;
- __uint32_t mxcsr;
-
- mxcsr = (env.__mxcsr_hi << 16) | (env.__mxcsr_lo);
- env.__mxcsr_hi = 0xffff;
- env.__mxcsr_lo = 0xffff;
- /*
- * XXX Using fldenvx() instead of fldenv() tells the compiler that this
- * instruction clobbers the i387 register stack. This happens because
- * we restore the tag word from the saved environment. Normally, this
- * would happen anyway and we wouldn't care, because the ABI allows
- * function calls to clobber the i387 regs. However, fesetenv() is
- * inlined, so we need to be more careful.
- */
- __fldenvx(env);
- if (__HAS_SSE()) {
- __ldmxcsr(mxcsr);
- }
- return (0);
+ fenv_t env = *envp;
+ __uint32_t mxcsr;
+
+ mxcsr = (env.__mxcsr_hi << 16) | (env.__mxcsr_lo);
+ env.__mxcsr_hi = 0xffff;
+ env.__mxcsr_lo = 0xffff;
+ /*
+ * XXX Using fldenvx() instead of fldenv() tells the compiler that this
+ * instruction clobbers the i387 register stack. This happens because
+ * we restore the tag word from the saved environment. Normally, this
+ * would happen anyway and we wouldn't care, because the ABI allows
+ * function calls to clobber the i387 regs. However, fesetenv() is
+ * inlined, so we need to be more careful.
+ */
+ __fldenvx(env);
+ if (__HAS_SSE()) {
+ __ldmxcsr(mxcsr);
+ }
+ return (0);
}
int
fegetexcept(void)
{
- __uint16_t control;
-
- /*
- * We assume that the masks for the x87 and the SSE unit are
- * the same.
- */
- __fnstcw(&control);
- return (~control & FE_ALL_EXCEPT);
+ __uint16_t control;
+
+ /*
+ * We assume that the masks for the x87 and the SSE unit are
+ * the same.
+ */
+ __fnstcw(&control);
+ return (~control & FE_ALL_EXCEPT);
}
diff --git a/libm/include/amd64/fenv.h b/libm/include/amd64/machine/fenv.h
index 1dc4215..f22a931 100644
--- a/libm/include/amd64/fenv.h
+++ b/libm/include/amd64/machine/fenv.h
@@ -24,17 +24,11 @@
* SUCH DAMAGE.
*/
-#ifndef _AMD64_FENV_H_
-#define _AMD64_FENV_H_
+#ifndef _AMD64_FENV_H_
+#define _AMD64_FENV_H_
#include <sys/types.h>
-/*
- * This file combines the OpenBSD include/fenv.h and machine/fenv.h to fit
- * the style of the other architectures (where we couldn't just take an
- * upstream fenv.h and had to write our own).
- */
-
__BEGIN_DECLS
/*
@@ -44,20 +38,20 @@ __BEGIN_DECLS
*
* We use such values that allow direct bitwise operations on FPU/SSE registers.
*/
-#define FE_INVALID 0x01
-#define FE_DENORMAL 0x02
-#define FE_DIVBYZERO 0x04
-#define FE_OVERFLOW 0x08
-#define FE_UNDERFLOW 0x10
-#define FE_INEXACT 0x20
+#define FE_INVALID 0x01
+#define FE_DENORMAL 0x02
+#define FE_DIVBYZERO 0x04
+#define FE_OVERFLOW 0x08
+#define FE_UNDERFLOW 0x10
+#define FE_INEXACT 0x20
/*
* The following symbol is simply the bitwise-inclusive OR of all floating-point
* exception constants defined above.
*/
-#define FE_ALL_EXCEPT (FE_INVALID | FE_DENORMAL | FE_DIVBYZERO | \
- FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT)
-#define _SSE_MASK_SHIFT 7
+#define FE_ALL_EXCEPT (FE_INVALID | FE_DENORMAL | FE_DIVBYZERO | \
+ FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT)
+#define _SSE_MASK_SHIFT 7
/*
* Each symbol representing the rounding direction, expands to an integer
@@ -65,45 +59,33 @@ __BEGIN_DECLS
*
* We use such values that allow direct bitwise operations on FPU/SSE registers.
*/
-#define FE_TONEAREST 0x000
-#define FE_DOWNWARD 0x400
-#define FE_UPWARD 0x800
-#define FE_TOWARDZERO 0xc00
+#define FE_TONEAREST 0x000
+#define FE_DOWNWARD 0x400
+#define FE_UPWARD 0x800
+#define FE_TOWARDZERO 0xc00
/*
* The following symbol is simply the bitwise-inclusive OR of all floating-point
* rounding direction constants defined above.
*/
-#define _X87_ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | \
- FE_TOWARDZERO)
-#define _SSE_ROUND_SHIFT 3
+#define _X87_ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | \
+ FE_TOWARDZERO)
+#define _SSE_ROUND_SHIFT 3
/*
* fenv_t represents the entire floating-point environment.
*/
-typedef struct {
- struct {
- unsigned int __control; /* Control word register */
- unsigned int __status; /* Status word register */
- unsigned int __tag; /* Tag word register */
- unsigned int __others[4]; /* EIP, Pointer Selector, etc */
- } __x87;
- unsigned int __mxcsr; /* Control, status register */
+typedef struct {
+ struct {
+ __uint32_t __control; /* Control word register */
+ __uint32_t __status; /* Status word register */
+ __uint32_t __tag; /* Tag word register */
+ __uint32_t __others[4]; /* EIP, Pointer Selector, etc */
+ } __x87;
+ __uint32_t __mxcsr; /* Control, status register */
} fenv_t;
/*
- * The following constant represents the default floating-point environment
- * (that is, the one installed at program startup) and has type pointer to
- * const-qualified fenv_t.
- *
- * It can be used as an argument to the functions within the <fenv.h> header
- * that manage the floating-point environment, namely fesetenv() and
- * feupdateenv().
- */
-extern fenv_t __fe_dfl_env;
-#define FE_DFL_ENV ((const fenv_t *)&__fe_dfl_env)
-
-/*
* fexcept_t represents the floating-point status flags collectively, including
* any status the implementation associates with the flags.
*
@@ -115,33 +97,8 @@ extern fenv_t __fe_dfl_env;
* A floating-point control mode is a system variable whose value may be set by
* the user to affect the subsequent behavior of floating-point arithmetic.
*/
-typedef unsigned int fexcept_t;
-
-/* C99 floating-point exception functions */
-int feclearexcept(int excepts);
-int fegetexceptflag(fexcept_t *flagp, int excepts);
-int fesetexceptflag(const fexcept_t *flagp, int excepts);
-/* feraiseexcept does not set the inexact flag on overflow/underflow */
-int feraiseexcept(int excepts);
-int fetestexcept(int excepts);
-
-/* C99 rounding control functions */
-int fegetround(void);
-int fesetround(int round);
-
-/* C99 floating-point environment functions */
-int fegetenv(fenv_t *__envp);
-int feholdexcept(fenv_t *__envp);
-int fesetenv(const fenv_t *envp);
-int feupdateenv(const fenv_t *__envp);
-
-#if __BSD_VISIBLE
-/* Additional support functions to set/query floating point traps */
-int feenableexcept(int __mask);
-int fedisableexcept(int __mask);
-int fegetexcept(void);
-#endif /* __BSD_VISIBLE */
+typedef __uint_32 fexcept_t;
__END_DECLS
-#endif /* !_AMD64_FENV_H_ */
+#endif /* !_AMD64_FENV_H_ */
diff --git a/libm/include/arm/fenv.h b/libm/include/arm/fenv.h
deleted file mode 100644
index a96f99e..0000000
--- a/libm/include/arm/fenv.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/*-
- * Copyright (c) 2004-2005 David Schultz <das@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: src/lib/msun/arm/fenv.h,v 1.5 2005/03/16 19:03:45 das Exp $
- */
-
-/*
- * Rewritten for Android.
- *
- * The ARM FPSCR is described here:
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0344b/Chdfafia.html
- */
-
-#ifndef _FENV_H_
-#define _FENV_H_
-
-#include <sys/types.h>
-
-__BEGIN_DECLS
-
-typedef __uint32_t fenv_t;
-typedef __uint32_t fexcept_t;
-
-/* Exception flags. */
-#define FE_INVALID 0x01
-#define FE_DIVBYZERO 0x02
-#define FE_OVERFLOW 0x04
-#define FE_UNDERFLOW 0x08
-#define FE_INEXACT 0x10
-#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
-#define _FPSCR_ENABLE_SHIFT 8
-#define _FPSCR_ENABLE_MASK (FE_ALL_EXCEPT << _FPSCR_ENABLE_SHIFT)
-
-/* Rounding modes. */
-#define FE_TONEAREST 0x0
-#define FE_UPWARD 0x1
-#define FE_DOWNWARD 0x2
-#define FE_TOWARDZERO 0x3
-#define _FPSCR_RMODE_SHIFT 22
-
-/* Default floating-point environment. */
-extern const fenv_t __fe_dfl_env;
-#define FE_DFL_ENV (&__fe_dfl_env)
-
-static __inline int fegetenv(fenv_t* __envp) {
- fenv_t _fpscr;
- __asm__ __volatile__("vmrs %0,fpscr" : "=r" (_fpscr));
- *__envp = _fpscr;
- return 0;
-}
-
-static __inline int fesetenv(const fenv_t* __envp) {
- fenv_t _fpscr = *__envp;
- __asm__ __volatile__("vmsr fpscr,%0" : :"ri" (_fpscr));
- return 0;
-}
-
-static __inline int feclearexcept(int __excepts) {
- fexcept_t __fpscr;
- fegetenv(&__fpscr);
- __fpscr &= ~__excepts;
- fesetenv(&__fpscr);
- return 0;
-}
-
-static __inline int fegetexceptflag(fexcept_t* __flagp, int __excepts) {
- fexcept_t __fpscr;
- fegetenv(&__fpscr);
- *__flagp = __fpscr & __excepts;
- return 0;
-}
-
-static __inline int fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
- fexcept_t __fpscr;
- fegetenv(&__fpscr);
- __fpscr &= ~__excepts;
- __fpscr |= *__flagp & __excepts;
- fesetenv(&__fpscr);
- return 0;
-}
-
-static __inline int feraiseexcept(int __excepts) {
- fexcept_t __ex = __excepts;
- fesetexceptflag(&__ex, __excepts);
- return 0;
-}
-
-static __inline int fetestexcept(int __excepts) {
- fexcept_t __fpscr;
- fegetenv(&__fpscr);
- return (__fpscr & __excepts);
-}
-
-static __inline int fegetround(void) {
- fenv_t _fpscr;
- fegetenv(&_fpscr);
- return ((_fpscr >> _FPSCR_RMODE_SHIFT) & 0x3);
-}
-
-static __inline int fesetround(int __round) {
- fenv_t _fpscr;
- fegetenv(&_fpscr);
- _fpscr &= ~(0x3 << _FPSCR_RMODE_SHIFT);
- _fpscr |= (__round << _FPSCR_RMODE_SHIFT);
- fesetenv(&_fpscr);
- return 0;
-}
-
-static __inline int feholdexcept(fenv_t* __envp) {
- fenv_t __env;
- fegetenv(&__env);
- *__envp = __env;
- __env &= ~(FE_ALL_EXCEPT | _FPSCR_ENABLE_MASK);
- fesetenv(&__env);
- return 0;
-}
-
-static __inline int feupdateenv(const fenv_t* __envp) {
- fexcept_t __fpscr;
- fegetenv(&__fpscr);
- fesetenv(__envp);
- feraiseexcept(__fpscr & FE_ALL_EXCEPT);
- return 0;
-}
-
-#if __BSD_VISIBLE
-
-static __inline int feenableexcept(int __mask) {
- fenv_t __old_fpscr, __new_fpscr;
- fegetenv(&__old_fpscr);
- __new_fpscr = __old_fpscr | (__mask & FE_ALL_EXCEPT) << _FPSCR_ENABLE_SHIFT;
- fesetenv(&__new_fpscr);
- return ((__old_fpscr >> _FPSCR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
-}
-
-static __inline int fedisableexcept(int __mask) {
- fenv_t __old_fpscr, __new_fpscr;
- fegetenv(&__old_fpscr);
- __new_fpscr = __old_fpscr & ~((__mask & FE_ALL_EXCEPT) << _FPSCR_ENABLE_SHIFT);
- fesetenv(&__new_fpscr);
- return ((__old_fpscr >> _FPSCR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
-}
-
-static __inline int fegetexcept(void) {
- fenv_t __fpscr;
- fegetenv(&__fpscr);
- return ((__fpscr & _FPSCR_ENABLE_MASK) >> _FPSCR_ENABLE_SHIFT);
-}
-
-#endif /* __BSD_VISIBLE */
-
-__END_DECLS
-
-#endif /* !_FENV_H_ */
diff --git a/libm/include/arm/machine/fenv.h b/libm/include/arm/machine/fenv.h
new file mode 100644
index 0000000..d8749dd
--- /dev/null
+++ b/libm/include/arm/machine/fenv.h
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 2004-2005 David Schultz <das@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: src/lib/msun/arm/fenv.h,v 1.5 2005/03/16 19:03:45 das Exp $
+ */
+
+/*
+ * Rewritten for Android.
+ *
+ * The ARM FPSCR is described here:
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0344b/Chdfafia.html
+ */
+
+#ifndef _ARM_FENV_H_
+#define _ARM_FENV_H_
+
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+typedef __uint32_t fenv_t;
+typedef __uint32_t fexcept_t;
+
+/* Exception flags. */
+#define FE_INVALID 0x01
+#define FE_DIVBYZERO 0x02
+#define FE_OVERFLOW 0x04
+#define FE_UNDERFLOW 0x08
+#define FE_INEXACT 0x10
+#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \
+ FE_OVERFLOW | FE_UNDERFLOW)
+
+#define _FPSCR_ENABLE_SHIFT 8
+#define _FPSCR_ENABLE_MASK (FE_ALL_EXCEPT << _FPSCR_ENABLE_SHIFT)
+
+/* Rounding modes. */
+#define FE_TONEAREST 0x0
+#define FE_UPWARD 0x1
+#define FE_DOWNWARD 0x2
+#define FE_TOWARDZERO 0x3
+
+#define _FPSCR_RMODE_SHIFT 22
+
+__END_DECLS
+
+#endif /* !_ARM_FENV_H_ */
diff --git a/libm/include/arm64/fenv.h b/libm/include/arm64/machine/fenv.h
index 32c3b1d..2efeee3 100644
--- a/libm/include/arm64/fenv.h
+++ b/libm/include/arm64/machine/fenv.h
@@ -38,8 +38,8 @@
* section 5.1.2 SIMD and Floating-Point Registers
*/
-#ifndef _FENV_H_
-#define _FENV_H_
+#ifndef _ARM64_FENV_H_
+#define _ARM64_FENV_H_
#include <sys/types.h>
@@ -54,15 +54,18 @@ typedef __uint32_t fexcept_t;
#define FE_OVERFLOW 0x04
#define FE_UNDERFLOW 0x08
#define FE_INEXACT 0x10
-#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
+#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \
+ FE_OVERFLOW | FE_UNDERFLOW)
+
#define _FPSCR_ENABLE_SHIFT 8
-#define _FPSCR_ENABLE_MASK (FE_ALL_EXCEPT << _FPSCR_ENABLE_SHIFT)
+#define _FPSCR_ENABLE_MASK (FE_ALL_EXCEPT << _FPSCR_ENABLE_SHIFT)
/* Rounding modes. */
#define FE_TONEAREST 0x0
#define FE_UPWARD 0x1
#define FE_DOWNWARD 0x2
#define FE_TOWARDZERO 0x3
+
#define _FPSCR_RMODE_SHIFT 22
#define FPCR_IOE (1 << 8)
@@ -113,120 +116,6 @@ typedef __uint32_t fexcept_t;
FPSR_Z | \
FPSR_N )
-/* Default floating-point environment. */
-extern const fenv_t __fe_dfl_env;
-#define FE_DFL_ENV (&__fe_dfl_env)
-
-static __inline int fegetenv(fenv_t* __envp) {
- fenv_t _fpcr, _fpsr;
- __asm__ __volatile__("mrs %0,fpcr" : "=r" (_fpcr));
- __asm__ __volatile__("mrs %0,fpsr" : "=r" (_fpsr));
- *__envp = (_fpcr | _fpsr);
- return 0;
-}
-
-static __inline int fesetenv(const fenv_t* __envp) {
- fenv_t _fpcr = (*__envp & FPCR_MASK);
- fenv_t _fpsr = (*__envp & FPSR_MASK);
- __asm__ __volatile__("msr fpcr,%0" : :"ri" (_fpcr));
- __asm__ __volatile__("msr fpsr,%0" : :"ri" (_fpsr));
- return 0;
-}
-
-static __inline int feclearexcept(int __excepts) {
- fexcept_t __fpscr;
- fegetenv(&__fpscr);
- __fpscr &= ~__excepts;
- fesetenv(&__fpscr);
- return 0;
-}
-
-static __inline int fegetexceptflag(fexcept_t* __flagp, int __excepts) {
- fexcept_t __fpscr;
- fegetenv(&__fpscr);
- *__flagp = __fpscr & __excepts;
- return 0;
-}
-
-static __inline int fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
- fexcept_t __fpscr;
- fegetenv(&__fpscr);
- __fpscr &= ~__excepts;
- __fpscr |= *__flagp & __excepts;
- fesetenv(&__fpscr);
- return 0;
-}
-
-static __inline int feraiseexcept(int __excepts) {
- fexcept_t __ex = __excepts;
- fesetexceptflag(&__ex, __excepts);
- return 0;
-}
-
-static __inline int fetestexcept(int __excepts) {
- fexcept_t __fpscr;
- fegetenv(&__fpscr);
- return (__fpscr & __excepts);
-}
-
-static __inline int fegetround(void) {
- fenv_t _fpscr;
- fegetenv(&_fpscr);
- return ((_fpscr >> _FPSCR_RMODE_SHIFT) & 0x3);
-}
-
-static __inline int fesetround(int __round) {
- fenv_t _fpscr;
- fegetenv(&_fpscr);
- _fpscr &= ~(0x3 << _FPSCR_RMODE_SHIFT);
- _fpscr |= (__round << _FPSCR_RMODE_SHIFT);
- fesetenv(&_fpscr);
- return 0;
-}
-
-static __inline int feholdexcept(fenv_t* __envp) {
- fenv_t __env;
- fegetenv(&__env);
- *__envp = __env;
- __env &= ~(FE_ALL_EXCEPT | _FPSCR_ENABLE_MASK);
- fesetenv(&__env);
- return 0;
-}
-
-static __inline int feupdateenv(const fenv_t* __envp) {
- fexcept_t __fpscr;
- fegetenv(&__fpscr);
- fesetenv(__envp);
- feraiseexcept(__fpscr & FE_ALL_EXCEPT);
- return 0;
-}
-
-#if __BSD_VISIBLE
-
-static __inline int feenableexcept(int __mask) {
- fenv_t __old_fpscr, __new_fpscr;
- fegetenv(&__old_fpscr);
- __new_fpscr = __old_fpscr | (__mask & FE_ALL_EXCEPT) << _FPSCR_ENABLE_SHIFT;
- fesetenv(&__new_fpscr);
- return ((__old_fpscr >> _FPSCR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
-}
-
-static __inline int fedisableexcept(int __mask) {
- fenv_t __old_fpscr, __new_fpscr;
- fegetenv(&__old_fpscr);
- __new_fpscr = __old_fpscr & ~((__mask & FE_ALL_EXCEPT) << _FPSCR_ENABLE_SHIFT);
- fesetenv(&__new_fpscr);
- return ((__old_fpscr >> _FPSCR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
-}
-
-static __inline int fegetexcept(void) {
- fenv_t __fpscr;
- fegetenv(&__fpscr);
- return ((__fpscr & _FPSCR_ENABLE_MASK) >> _FPSCR_ENABLE_SHIFT);
-}
-
-#endif /* __BSD_VISIBLE */
-
__END_DECLS
-#endif /* !_FENV_H_ */
+#endif /* !_ARM64_FENV_H_ */
diff --git a/libm/include/fenv.h b/libm/include/fenv.h
new file mode 100644
index 0000000..6966e0d
--- /dev/null
+++ b/libm/include/fenv.h
@@ -0,0 +1,69 @@
+/* $OpenBSD: fenv.h,v 1.2 2011/05/25 21:46:49 martynas Exp $ */
+/* $NetBSD: fenv.h,v 1.2.4.1 2011/02/08 16:18:55 bouyer Exp $ */
+
+/*
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef _FENV_H_
+#define _FENV_H_
+
+#include <sys/cdefs.h>
+#include <machine/fenv.h>
+
+__BEGIN_DECLS
+
+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 *);
+
+int feenableexcept(int);
+int fedisableexcept(int);
+int fegetexcept(void);
+
+/*
+ * The following constant represents the default floating-point environment
+ * (that is, the one installed at program startup) and has type pointer to
+ * const-qualified fenv_t.
+ *
+ * It can be used as an argument to the functions that manage the floating-point
+ * environment, namely fesetenv() and feupdateenv().
+ */
+extern const fenv_t __fe_dfl_env;
+#define FE_DFL_ENV (&__fe_dfl_env)
+
+__END_DECLS
+
+#endif /* ! _FENV_H_ */
diff --git a/libm/include/i387/fenv.h b/libm/include/i387/machine/fenv.h
index c0421c0..f3fabb6 100644
--- a/libm/include/i387/fenv.h
+++ b/libm/include/i387/machine/fenv.h
@@ -26,76 +26,46 @@
* $FreeBSD: src/lib/msun/i387/fenv.h,v 1.4 2005/03/17 22:21:46 das Exp $
*/
-#ifndef _FENV_H_
-#define _FENV_H_
+#ifndef _I387_FENV_H_
+#define _I387_FENV_H_
#include <sys/types.h>
__BEGIN_DECLS
-/*
+/*
* To preserve binary compatibility with FreeBSD 5.3, we pack the
* mxcsr into some reserved fields, rather than changing sizeof(fenv_t).
*/
typedef struct {
- __uint16_t __control;
- __uint16_t __mxcsr_hi;
- __uint16_t __status;
- __uint16_t __mxcsr_lo;
- __uint32_t __tag;
- char __other[16];
+ __uint16_t __control;
+ __uint16_t __mxcsr_hi;
+ __uint16_t __status;
+ __uint16_t __mxcsr_lo;
+ __uint32_t __tag;
+ char __other[16];
} fenv_t;
-typedef __uint16_t fexcept_t;
+typedef __uint16_t fexcept_t;
/* Exception flags */
-#define FE_INVALID 0x01
-#define FE_DENORMAL 0x02
-#define FE_DIVBYZERO 0x04
-#define FE_OVERFLOW 0x08
-#define FE_UNDERFLOW 0x10
-#define FE_INEXACT 0x20
-#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_DENORMAL | FE_INEXACT | \
- FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
+#define FE_INVALID 0x01
+#define FE_DENORMAL 0x02
+#define FE_DIVBYZERO 0x04
+#define FE_OVERFLOW 0x08
+#define FE_UNDERFLOW 0x10
+#define FE_INEXACT 0x20
+#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_DENORMAL | FE_INEXACT | \
+ FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
/* Rounding modes */
-#define FE_TONEAREST 0x0000
-#define FE_DOWNWARD 0x0400
-#define FE_UPWARD 0x0800
-#define FE_TOWARDZERO 0x0c00
-#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \
- FE_UPWARD | FE_TOWARDZERO)
-
-/* Default floating-point environment */
-extern const fenv_t __fe_dfl_env;
-#define FE_DFL_ENV (&__fe_dfl_env)
-
-/* C99 floating-point exception functions */
-int feclearexcept(int excepts);
-int fegetexceptflag(fexcept_t *flagp, int excepts);
-int fesetexceptflag(const fexcept_t *flagp, int excepts);
-/* feraiseexcept does not set the inexact flag on overflow/underflow */
-int feraiseexcept(int excepts);
-int fetestexcept(int excepts);
-
-/* C99 rounding control functions */
-int fegetround(void);
-int fesetround(int round);
-
-/* C99 floating-point environment functions */
-int fegetenv(fenv_t *__envp);
-int feholdexcept(fenv_t *__envp);
-int fesetenv(const fenv_t *envp);
-int feupdateenv(const fenv_t *__envp);
-
-#if __BSD_VISIBLE
-/* Additional support functions to set/query floating point traps */
-int feenableexcept(int __mask);
-int fedisableexcept(int __mask);
-int fegetexcept(void);
-
-#endif /* __BSD_VISIBLE */
+#define FE_TONEAREST 0x0000
+#define FE_DOWNWARD 0x0400
+#define FE_UPWARD 0x0800
+#define FE_TOWARDZERO 0x0c00
+#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \
+ FE_UPWARD | FE_TOWARDZERO)
__END_DECLS
-#endif /* !_FENV_H_ */
+#endif /* !I387_FENV_H_ */
diff --git a/libm/include/mips/fenv.h b/libm/include/mips/fenv.h
deleted file mode 100644
index ed69cf8..0000000
--- a/libm/include/mips/fenv.h
+++ /dev/null
@@ -1,225 +0,0 @@
-/*-
- * Copyright (c) 2004-2005 David Schultz <das@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: src/lib/msun/arm/fenv.h,v 1.5 2005/03/16 19:03:45 das Exp $
- */
-
-/*
- Rewritten for Android.
-*/
-
-/* MIPS FPU floating point control register bits.
- *
- * 31-25 -> floating point conditions code bits set by FP compare
- * instructions
- * 24 -> flush denormalized results to zero instead of
- * causing unimplemented operation exception.
- * 23 -> Condition bit
- * 22 -> In conjunction with FS detects denormalized
- * operands and replaces them internally with 0.
- * 21 -> In conjunction with FS forces denormalized operands
- * to the closest normalized value.
- * 20-18 -> reserved (read as 0, write with 0)
- * 17 -> cause bit for unimplemented operation
- * 16 -> cause bit for invalid exception
- * 15 -> cause bit for division by zero exception
- * 14 -> cause bit for overflow exception
- * 13 -> cause bit for underflow exception
- * 12 -> cause bit for inexact exception
- * 11 -> enable exception for invalid exception
- * 10 -> enable exception for division by zero exception
- * 9 -> enable exception for overflow exception
- * 8 -> enable exception for underflow exception
- * 7 -> enable exception for inexact exception
- * 6 -> flag invalid exception
- * 5 -> flag division by zero exception
- * 4 -> flag overflow exception
- * 3 -> flag underflow exception
- * 2 -> flag inexact exception
- * 1-0 -> rounding control
- *
- *
- * Rounding Control:
- * 00 - rounding to nearest (RN)
- * 01 - rounding toward zero (RZ)
- * 10 - rounding (up) toward plus infinity (RP)
- * 11 - rounding (down)toward minus infinity (RM)
- */
-
-#ifndef _FENV_H_
-#define _FENV_H_
-
-#include <sys/types.h>
-
-__BEGIN_DECLS
-
-typedef __uint32_t fenv_t;
-typedef __uint32_t fexcept_t;
-
-/* Exception flags */
-#define FE_INVALID 0x40
-#define FE_DIVBYZERO 0x20
-#define FE_OVERFLOW 0x10
-#define FE_UNDERFLOW 0x08
-#define FE_INEXACT 0x04
-#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \
- FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
-#define _FCSR_CAUSE_SHIFT 10
-#define _ENABLE_SHIFT 5
-#define _FCSR_ENABLE_MASK (FE_ALL_EXCEPT << _ENABLE_SHIFT)
-
-/* Rounding modes */
-#define FE_TONEAREST 0x0000
-#define FE_TOWARDZERO 0x0001
-#define FE_UPWARD 0x0002
-#define FE_DOWNWARD 0x0003
-#define _FCSR_RMODE_SHIFT 0
-#define _FCSR_RMASK 0x3
-/* Default floating-point environment */
-extern const fenv_t __fe_dfl_env;
-#define FE_DFL_ENV (&__fe_dfl_env)
-
-static __inline int fegetenv(fenv_t* __envp) {
- fenv_t _fcsr = 0;
-#ifdef __mips_hard_float
- __asm__ __volatile__("cfc1 %0,$31" : "=r" (_fcsr));
-#endif
- *__envp = _fcsr;
- return 0;
-}
-
-static __inline int fesetenv(const fenv_t* __envp) {
- fenv_t _fcsr = *__envp;
-#ifdef __mips_hard_float
- __asm__ __volatile__("ctc1 %0,$31" : : "r" (_fcsr));
-#endif
- return 0;
-}
-
-static __inline int feclearexcept(int __excepts) {
- fexcept_t __fcsr;
- fegetenv(&__fcsr);
- __excepts &= FE_ALL_EXCEPT;
- __fcsr &= ~(__excepts | (__excepts << _FCSR_CAUSE_SHIFT));
- fesetenv(&__fcsr);
- return 0;
-}
-
-static __inline int fegetexceptflag(fexcept_t* __flagp, int __excepts) {
- fexcept_t __fcsr;
- fegetenv(&__fcsr);
- *__flagp = __fcsr & __excepts & FE_ALL_EXCEPT;
- return 0;
-}
-
-static __inline int fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
- fexcept_t __fcsr;
- fegetenv(&__fcsr);
- /* Ensure that flags are all legal */
- __excepts &= FE_ALL_EXCEPT;
- __fcsr &= ~__excepts;
- __fcsr |= *__flagp & __excepts;
- fesetenv(&__fcsr);
- return 0;
-}
-
-static __inline int feraiseexcept(int __excepts) {
- fexcept_t __fcsr;
- fegetenv(&__fcsr);
- /* Ensure that flags are all legal */
- __excepts &= FE_ALL_EXCEPT;
- /* Cause bit needs to be set as well for generating the exception*/
- __fcsr |= __excepts | (__excepts << _FCSR_CAUSE_SHIFT);
- fesetenv(&__fcsr);
- return 0;
-}
-
-static __inline int fetestexcept(int __excepts) {
- fexcept_t __FCSR;
- fegetenv(&__FCSR);
- return (__FCSR & __excepts & FE_ALL_EXCEPT);
-}
-
-static __inline int fegetround(void) {
- fenv_t _fcsr;
- fegetenv(&_fcsr);
- return (_fcsr & _FCSR_RMASK);
-}
-
-static __inline int fesetround(int __round) {
- fenv_t _fcsr;
- fegetenv(&_fcsr);
- _fcsr &= ~_FCSR_RMASK;
- _fcsr |= (__round & _FCSR_RMASK ) ;
- fesetenv(&_fcsr);
- return 0;
-}
-
-static __inline int feholdexcept(fenv_t* __envp) {
- fenv_t __env;
- fegetenv(&__env);
- *__envp = __env;
- __env &= ~(FE_ALL_EXCEPT | _FCSR_ENABLE_MASK);
- fesetenv(&__env);
- return 0;
-}
-
-static __inline int feupdateenv(const fenv_t* __envp) {
- fexcept_t __fcsr;
- fegetenv(&__fcsr);
- fesetenv(__envp);
- feraiseexcept(__fcsr & FE_ALL_EXCEPT);
- return 0;
-}
-
-#if __BSD_VISIBLE
-
-static __inline int feenableexcept(int __mask) {
- fenv_t __old_fcsr, __new_fcsr;
- fegetenv(&__old_fcsr);
- __new_fcsr = __old_fcsr | (__mask & FE_ALL_EXCEPT) << _ENABLE_SHIFT;
- fesetenv(&__new_fcsr);
- return ((__old_fcsr >> _ENABLE_SHIFT) & FE_ALL_EXCEPT);
-}
-
-static __inline int fedisableexcept(int __mask) {
- fenv_t __old_fcsr, __new_fcsr;
- fegetenv(&__old_fcsr);
- __new_fcsr = __old_fcsr & ~((__mask & FE_ALL_EXCEPT) << _ENABLE_SHIFT);
- fesetenv(&__new_fcsr);
- return ((__old_fcsr >> _ENABLE_SHIFT) & FE_ALL_EXCEPT);
-}
-
-static __inline int fegetexcept(void) {
- fenv_t __fcsr;
- fegetenv(&__fcsr);
- return ((__fcsr & _FCSR_ENABLE_MASK) >> _ENABLE_SHIFT);
-}
-
-#endif /* __BSD_VISIBLE */
-
-__END_DECLS
-
-#endif /* !_FENV_H_ */
diff --git a/libm/include/mips/machine/fenv.h b/libm/include/mips/machine/fenv.h
new file mode 100644
index 0000000..dcd0eb2
--- /dev/null
+++ b/libm/include/mips/machine/fenv.h
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 2004-2005 David Schultz <das@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: src/lib/msun/arm/fenv.h,v 1.5 2005/03/16 19:03:45 das Exp $
+ */
+
+/*
+ Rewritten for Android.
+*/
+
+/* MIPS FPU floating point control register bits.
+ *
+ * 31-25 -> floating point conditions code bits set by FP compare
+ * instructions
+ * 24 -> flush denormalized results to zero instead of
+ * causing unimplemented operation exception.
+ * 23 -> Condition bit
+ * 22 -> In conjunction with FS detects denormalized
+ * operands and replaces them internally with 0.
+ * 21 -> In conjunction with FS forces denormalized operands
+ * to the closest normalized value.
+ * 20-18 -> reserved (read as 0, write with 0)
+ * 17 -> cause bit for unimplemented operation
+ * 16 -> cause bit for invalid exception
+ * 15 -> cause bit for division by zero exception
+ * 14 -> cause bit for overflow exception
+ * 13 -> cause bit for underflow exception
+ * 12 -> cause bit for inexact exception
+ * 11 -> enable exception for invalid exception
+ * 10 -> enable exception for division by zero exception
+ * 9 -> enable exception for overflow exception
+ * 8 -> enable exception for underflow exception
+ * 7 -> enable exception for inexact exception
+ * 6 -> flag invalid exception
+ * 5 -> flag division by zero exception
+ * 4 -> flag overflow exception
+ * 3 -> flag underflow exception
+ * 2 -> flag inexact exception
+ * 1-0 -> rounding control
+ *
+ *
+ * Rounding Control:
+ * 00 - rounding to nearest (RN)
+ * 01 - rounding toward zero (RZ)
+ * 10 - rounding (up) toward plus infinity (RP)
+ * 11 - rounding (down)toward minus infinity (RM)
+ */
+
+#ifndef _MIPS_FENV_H_
+#define _MIPS_FENV_H_
+
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+typedef __uint32_t fenv_t;
+typedef __uint32_t lfexcept_t;
+
+/* Exception flags */
+#define FE_INVALID 0x40
+#define FE_DIVBYZERO 0x20
+#define FE_OVERFLOW 0x10
+#define FE_UNDERFLOW 0x08
+#define FE_INEXACT 0x04
+#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \
+ FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
+
+#define _FCSR_CAUSE_SHIFT 10
+#define _ENABLE_SHIFT 5
+#define _FCSR_ENABLE_MASK (FE_ALL_EXCEPT << _ENABLE_SHIFT)
+
+/* Rounding modes */
+#define FE_TONEAREST 0x0000
+#define FE_TOWARDZERO 0x0001
+#define FE_UPWARD 0x0002
+#define FE_DOWNWARD 0x0003
+
+#define _FCSR_RMODE_SHIFT 0
+#define _FCSR_RMASK 0x3
+
+__END_DECLS
+
+#endif /* !_MIPS_FENV_H_ */
diff --git a/libm/mips/fenv.c b/libm/mips/fenv.c
index b5f52da..893bc30 100644
--- a/libm/mips/fenv.c
+++ b/libm/mips/fenv.c
@@ -33,3 +33,118 @@
* this as a default environment.
*/
const fenv_t __fe_dfl_env = 0;
+
+int fegetenv(fenv_t* __envp) {
+ fenv_t _fcsr = 0;
+#ifdef __mips_hard_float
+ __asm__ __volatile__("cfc1 %0,$31" : "=r" (_fcsr));
+#endif
+ *__envp = _fcsr;
+ return 0;
+}
+
+int fesetenv(const fenv_t* __envp) {
+ fenv_t _fcsr = *__envp;
+#ifdef __mips_hard_float
+ __asm__ __volatile__("ctc1 %0,$31" : : "r" (_fcsr));
+#endif
+ return 0;
+}
+
+int feclearexcept(int __excepts) {
+ fexcept_t __fcsr;
+ fegetenv(&__fcsr);
+ __excepts &= FE_ALL_EXCEPT;
+ __fcsr &= ~(__excepts | (__excepts << _FCSR_CAUSE_SHIFT));
+ fesetenv(&__fcsr);
+ return 0;
+}
+
+int fegetexceptflag(fexcept_t* __flagp, int __excepts) {
+ fexcept_t __fcsr;
+ fegetenv(&__fcsr);
+ *__flagp = __fcsr & __excepts & FE_ALL_EXCEPT;
+ return 0;
+}
+
+int fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
+ fexcept_t __fcsr;
+ fegetenv(&__fcsr);
+ /* Ensure that flags are all legal */
+ __excepts &= FE_ALL_EXCEPT;
+ __fcsr &= ~__excepts;
+ __fcsr |= *__flagp & __excepts;
+ fesetenv(&__fcsr);
+ return 0;
+}
+
+int feraiseexcept(int __excepts) {
+ fexcept_t __fcsr;
+ fegetenv(&__fcsr);
+ /* Ensure that flags are all legal */
+ __excepts &= FE_ALL_EXCEPT;
+ /* Cause bit needs to be set as well for generating the exception*/
+ __fcsr |= __excepts | (__excepts << _FCSR_CAUSE_SHIFT);
+ fesetenv(&__fcsr);
+ return 0;
+}
+
+int fetestexcept(int __excepts) {
+ fexcept_t __FCSR;
+ fegetenv(&__FCSR);
+ return (__FCSR & __excepts & FE_ALL_EXCEPT);
+}
+
+int fegetround(void) {
+ fenv_t _fcsr;
+ fegetenv(&_fcsr);
+ return (_fcsr & _FCSR_RMASK);
+}
+
+int fesetround(int __round) {
+ fenv_t _fcsr;
+ fegetenv(&_fcsr);
+ _fcsr &= ~_FCSR_RMASK;
+ _fcsr |= (__round & _FCSR_RMASK ) ;
+ fesetenv(&_fcsr);
+ return 0;
+}
+
+int feholdexcept(fenv_t* __envp) {
+ fenv_t __env;
+ fegetenv(&__env);
+ *__envp = __env;
+ __env &= ~(FE_ALL_EXCEPT | _FCSR_ENABLE_MASK);
+ fesetenv(&__env);
+ return 0;
+}
+
+int feupdateenv(const fenv_t* __envp) {
+ fexcept_t __fcsr;
+ fegetenv(&__fcsr);
+ fesetenv(__envp);
+ feraiseexcept(__fcsr & FE_ALL_EXCEPT);
+ return 0;
+}
+
+int feenableexcept(int __mask) {
+ fenv_t __old_fcsr, __new_fcsr;
+ fegetenv(&__old_fcsr);
+ __new_fcsr = __old_fcsr | (__mask & FE_ALL_EXCEPT) << _ENABLE_SHIFT;
+ fesetenv(&__new_fcsr);
+ return ((__old_fcsr >> _ENABLE_SHIFT) & FE_ALL_EXCEPT);
+}
+
+int fedisableexcept(int __mask) {
+ fenv_t __old_fcsr, __new_fcsr;
+ fegetenv(&__old_fcsr);
+ __new_fcsr = __old_fcsr & ~((__mask & FE_ALL_EXCEPT) << _ENABLE_SHIFT);
+ fesetenv(&__new_fcsr);
+ return ((__old_fcsr >> _ENABLE_SHIFT) & FE_ALL_EXCEPT);
+}
+
+int fegetexcept(void) {
+ fenv_t __fcsr;
+ fegetenv(&__fcsr);
+ return ((__fcsr & _FCSR_ENABLE_MASK) >> _ENABLE_SHIFT);
+}