From 2d367905a2e1b950f79b408141eea07c222b590b Mon Sep 17 00:00:00 2001 From: Calin Juravle Date: Tue, 25 Feb 2014 14:49:41 +0000 Subject: [PATCH] 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 --- libm/amd64/fenv.c | 334 ++++++++--------- libm/arm/fenv.c | 103 ++++++ libm/arm64/fenv.c | 106 ++++++ libm/i387/fenv.c | 454 ++++++++++++------------ libm/include/amd64/{ => machine}/fenv.h | 99 ++---- libm/include/arm/fenv.h | 176 --------- libm/include/arm/machine/fenv.h | 68 ++++ libm/include/arm64/{ => machine}/fenv.h | 127 +------ libm/include/fenv.h | 69 ++++ libm/include/i387/{ => machine}/fenv.h | 80 ++--- libm/include/mips/fenv.h | 225 ------------ libm/include/mips/machine/fenv.h | 105 ++++++ libm/mips/fenv.c | 115 ++++++ 13 files changed, 1021 insertions(+), 1040 deletions(-) rename libm/include/amd64/{ => machine}/fenv.h (54%) delete mode 100644 libm/include/arm/fenv.h create mode 100644 libm/include/arm/machine/fenv.h rename libm/include/arm64/{ => machine}/fenv.h (56%) create mode 100644 libm/include/fenv.h rename libm/include/i387/{ => machine}/fenv.h (51%) delete mode 100644 libm/include/mips/fenv.h create mode 100644 libm/include/mips/machine/fenv.h diff --git a/libm/amd64/fenv.c b/libm/amd64/fenv.c index 7ad3be782..b2c017be8 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 @@ -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 current x87 floating-point environment */ + __asm__ __volatile__ ("fnstenv %0" : "=m" (*envp)); - /* Store the MXCSR register state */ - __asm__ __volatile__ ("stmxcsr %0" : "=m" (envp->__mxcsr)); + /* 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)); + /* + * 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); + 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 469f198c3..a0108e8d6 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 27c405fdb..9db21efd9 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 89ddc55ed..3ab9c585b 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; + 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); + /* 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; + 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); - } - } + 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); + 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; + __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); + __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; + __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); + __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; + __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); + __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; + __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); + 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; + __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); + 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; + 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); + 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; + __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); + 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; + __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); + 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; + __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); + /* + * 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; + __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); - } + 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; + 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); + 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; + __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); + /* + * 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 similarity index 54% rename from libm/include/amd64/fenv.h rename to libm/include/amd64/machine/fenv.h index 1dc4215af..f22a931f5 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 -/* - * 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,44 +59,32 @@ __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 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 a96f99ed8..000000000 --- a/libm/include/arm/fenv.h +++ /dev/null @@ -1,176 +0,0 @@ -/*- - * Copyright (c) 2004-2005 David Schultz - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: 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 - -__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 000000000..d8749dd97 --- /dev/null +++ b/libm/include/arm/machine/fenv.h @@ -0,0 +1,68 @@ +/*- + * Copyright (c) 2004-2005 David Schultz + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: 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 + +__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 similarity index 56% rename from libm/include/arm64/fenv.h rename to libm/include/arm64/machine/fenv.h index 32c3b1d06..2efeee3da 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 @@ -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 000000000..6966e0d6b --- /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 +#include + +__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 similarity index 51% rename from libm/include/i387/fenv.h rename to libm/include/i387/machine/fenv.h index c0421c026..f3fabb641 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 __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 ed69cf877..000000000 --- a/libm/include/mips/fenv.h +++ /dev/null @@ -1,225 +0,0 @@ -/*- - * Copyright (c) 2004-2005 David Schultz - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: 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 - -__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 000000000..dcd0eb2de --- /dev/null +++ b/libm/include/mips/machine/fenv.h @@ -0,0 +1,105 @@ +/*- + * Copyright (c) 2004-2005 David Schultz + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: 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 + +__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 b5f52dad7..893bc3009 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); +}