Added FreeBSD fenv implementation - tested with dmd port, seems that it works
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35437 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
5fb7d0a580
commit
38ecc1a764
218
headers/posix/arch/arm/fenv.h
Normal file
218
headers/posix/arch/arm/fenv.h
Normal file
@ -0,0 +1,218 @@
|
||||
/*-
|
||||
* 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$
|
||||
*/
|
||||
|
||||
#ifndef _FENV_H_
|
||||
#define _FENV_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
typedef uint32 fenv_t;
|
||||
typedef uint32 fexcept_t;
|
||||
|
||||
/* Exception flags */
|
||||
#define FE_INVALID 0x0001
|
||||
#define FE_DIVBYZERO 0x0002
|
||||
#define FE_OVERFLOW 0x0004
|
||||
#define FE_UNDERFLOW 0x0008
|
||||
#define FE_INEXACT 0x0010
|
||||
#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \
|
||||
FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
|
||||
|
||||
/* Rounding modes */
|
||||
#define FE_TONEAREST 0x0000
|
||||
#define FE_TOWARDZERO 0x0001
|
||||
#define FE_UPWARD 0x0002
|
||||
#define FE_DOWNWARD 0x0003
|
||||
#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \
|
||||
FE_UPWARD | FE_TOWARDZERO)
|
||||
__BEGIN_DECLS
|
||||
|
||||
/* Default floating-point environment */
|
||||
extern const fenv_t __fe_dfl_env;
|
||||
#define FE_DFL_ENV (&__fe_dfl_env)
|
||||
|
||||
/* We need to be able to map status flag positions to mask flag positions */
|
||||
#define _FPUSW_SHIFT 16
|
||||
#define _ENABLE_MASK (FE_ALL_EXCEPT << _FPUSW_SHIFT)
|
||||
|
||||
#ifdef ARM_HARD_FLOAT
|
||||
#define __rfs(__fpsr) __asm __volatile("rfs %0" : "=r" (*(__fpsr)))
|
||||
#define __wfs(__fpsr) __asm __volatile("wfs %0" : : "r" (__fpsr))
|
||||
#else
|
||||
#define __rfs(__fpsr)
|
||||
#define __wfs(__fpsr)
|
||||
#endif
|
||||
|
||||
static __inline int
|
||||
feclearexcept(int __excepts)
|
||||
{
|
||||
fexcept_t __fpsr;
|
||||
|
||||
__rfs(&__fpsr);
|
||||
__fpsr &= ~__excepts;
|
||||
__wfs(__fpsr);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
fegetexceptflag(fexcept_t *__flagp, int __excepts)
|
||||
{
|
||||
fexcept_t __fpsr;
|
||||
|
||||
__rfs(&__fpsr);
|
||||
*__flagp = __fpsr & __excepts;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
fesetexceptflag(const fexcept_t *__flagp, int __excepts)
|
||||
{
|
||||
fexcept_t __fpsr;
|
||||
|
||||
__rfs(&__fpsr);
|
||||
__fpsr &= ~__excepts;
|
||||
__fpsr |= *__flagp & __excepts;
|
||||
__wfs(__fpsr);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
feraiseexcept(int __excepts)
|
||||
{
|
||||
fexcept_t __ex = __excepts;
|
||||
|
||||
fesetexceptflag(&__ex, __excepts); /* XXX */
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
fetestexcept(int __excepts)
|
||||
{
|
||||
fexcept_t __fpsr;
|
||||
|
||||
__rfs(&__fpsr);
|
||||
return (__fpsr & __excepts);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
fegetround(void)
|
||||
{
|
||||
|
||||
/*
|
||||
* Apparently, the rounding mode is specified as part of the
|
||||
* instruction format on ARM, so the dynamic rounding mode is
|
||||
* indeterminate. Some FPUs may differ.
|
||||
*/
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
fesetround(int __round)
|
||||
{
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
fegetenv(fenv_t *__envp)
|
||||
{
|
||||
|
||||
__rfs(__envp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
feholdexcept(fenv_t *__envp)
|
||||
{
|
||||
fenv_t __env;
|
||||
|
||||
__rfs(&__env);
|
||||
*__envp = __env;
|
||||
__env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
|
||||
__wfs(__env);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
fesetenv(const fenv_t *__envp)
|
||||
{
|
||||
|
||||
__wfs(*__envp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
feupdateenv(const fenv_t *__envp)
|
||||
{
|
||||
fexcept_t __fpsr;
|
||||
|
||||
__rfs(&__fpsr);
|
||||
__wfs(*__envp);
|
||||
feraiseexcept(__fpsr & FE_ALL_EXCEPT);
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if __BSD_VISIBLE
|
||||
|
||||
static __inline int
|
||||
feenableexcept(int __mask)
|
||||
{
|
||||
fenv_t __old_fpsr, __new_fpsr;
|
||||
|
||||
__rfs(&__old_fpsr);
|
||||
__new_fpsr = __old_fpsr | (__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT;
|
||||
__wfs(__new_fpsr);
|
||||
return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
fedisableexcept(int __mask)
|
||||
{
|
||||
fenv_t __old_fpsr, __new_fpsr;
|
||||
|
||||
__rfs(&__old_fpsr);
|
||||
__new_fpsr = __old_fpsr & ~((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT);
|
||||
__wfs(__new_fpsr);
|
||||
return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
fegetexcept(void)
|
||||
{
|
||||
fenv_t __fpsr;
|
||||
|
||||
__rfs(&__fpsr);
|
||||
return ((__fpsr & _ENABLE_MASK) >> _FPUSW_SHIFT);
|
||||
}
|
||||
|
||||
#endif /* __BSD_VISIBLE */
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* !_FENV_H_ */
|
269
headers/posix/arch/ppc/fenv.h
Normal file
269
headers/posix/arch/ppc/fenv.h
Normal file
@ -0,0 +1,269 @@
|
||||
/*-
|
||||
* 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$
|
||||
*/
|
||||
|
||||
#ifndef _FENV_H_
|
||||
#define _FENV_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
typedef uint32 fenv_t;
|
||||
typedef uint32 fexcept_t;
|
||||
|
||||
/* Exception flags */
|
||||
#define FE_INEXACT 0x02000000
|
||||
#define FE_DIVBYZERO 0x04000000
|
||||
#define FE_UNDERFLOW 0x08000000
|
||||
#define FE_OVERFLOW 0x10000000
|
||||
#define FE_INVALID 0x20000000 /* all types of invalid FP ops */
|
||||
|
||||
/*
|
||||
* The PowerPC architecture has extra invalid flags that indicate the
|
||||
* specific type of invalid operation occurred. These flags may be
|
||||
* tested, set, and cleared---but not masked---separately. All of
|
||||
* these bits are cleared when FE_INVALID is cleared, but only
|
||||
* FE_VXSOFT is set when FE_INVALID is explicitly set in software.
|
||||
*/
|
||||
#define FE_VXCVI 0x00000100 /* invalid integer convert */
|
||||
#define FE_VXSQRT 0x00000200 /* square root of a negative */
|
||||
#define FE_VXSOFT 0x00000400 /* software-requested exception */
|
||||
#define FE_VXVC 0x00080000 /* ordered comparison involving NaN */
|
||||
#define FE_VXIMZ 0x00100000 /* inf * 0 */
|
||||
#define FE_VXZDZ 0x00200000 /* 0 / 0 */
|
||||
#define FE_VXIDI 0x00400000 /* inf / inf */
|
||||
#define FE_VXISI 0x00800000 /* inf - inf */
|
||||
#define FE_VXSNAN 0x01000000 /* operation on a signalling NaN */
|
||||
#define FE_ALL_INVALID (FE_VXCVI | FE_VXSQRT | FE_VXSOFT | FE_VXVC | \
|
||||
FE_VXIMZ | FE_VXZDZ | FE_VXIDI | FE_VXISI | \
|
||||
FE_VXSNAN | FE_INVALID)
|
||||
#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \
|
||||
FE_ALL_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
|
||||
|
||||
/* Rounding modes */
|
||||
#define FE_TONEAREST 0x0000
|
||||
#define FE_TOWARDZERO 0x0001
|
||||
#define FE_UPWARD 0x0002
|
||||
#define FE_DOWNWARD 0x0003
|
||||
#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \
|
||||
FE_UPWARD | FE_TOWARDZERO)
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/* Default floating-point environment */
|
||||
extern const fenv_t __fe_dfl_env;
|
||||
#define FE_DFL_ENV (&__fe_dfl_env)
|
||||
|
||||
/* We need to be able to map status flag positions to mask flag positions */
|
||||
#define _FPUSW_SHIFT 22
|
||||
#define _ENABLE_MASK ((FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \
|
||||
FE_OVERFLOW | FE_UNDERFLOW) >> _FPUSW_SHIFT)
|
||||
|
||||
#ifndef _SOFT_FLOAT
|
||||
#define __mffs(__env) __asm __volatile("mffs %0" : "=f" (*(__env)))
|
||||
#define __mtfsf(__env) __asm __volatile("mtfsf 255,%0" : : "f" (__env))
|
||||
#else
|
||||
#define __mffs(__env)
|
||||
#define __mtfsf(__env)
|
||||
#endif
|
||||
|
||||
union __fpscr {
|
||||
double __d;
|
||||
struct {
|
||||
__uint32_t __junk;
|
||||
fenv_t __reg;
|
||||
} __bits;
|
||||
};
|
||||
|
||||
static __inline int
|
||||
feclearexcept(int __excepts)
|
||||
{
|
||||
union __fpscr __r;
|
||||
|
||||
if (__excepts & FE_INVALID)
|
||||
__excepts |= FE_ALL_INVALID;
|
||||
__mffs(&__r.__d);
|
||||
__r.__bits.__reg &= ~__excepts;
|
||||
__mtfsf(__r.__d);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
fegetexceptflag(fexcept_t *__flagp, int __excepts)
|
||||
{
|
||||
union __fpscr __r;
|
||||
|
||||
__mffs(&__r.__d);
|
||||
*__flagp = __r.__bits.__reg & __excepts;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
fesetexceptflag(const fexcept_t *__flagp, int __excepts)
|
||||
{
|
||||
union __fpscr __r;
|
||||
|
||||
if (__excepts & FE_INVALID)
|
||||
__excepts |= FE_ALL_EXCEPT;
|
||||
__mffs(&__r.__d);
|
||||
__r.__bits.__reg &= ~__excepts;
|
||||
__r.__bits.__reg |= *__flagp & __excepts;
|
||||
__mtfsf(__r.__d);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
feraiseexcept(int __excepts)
|
||||
{
|
||||
union __fpscr __r;
|
||||
|
||||
if (__excepts & FE_INVALID)
|
||||
__excepts |= FE_VXSOFT;
|
||||
__mffs(&__r.__d);
|
||||
__r.__bits.__reg |= __excepts;
|
||||
__mtfsf(__r.__d);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
fetestexcept(int __excepts)
|
||||
{
|
||||
union __fpscr __r;
|
||||
|
||||
__mffs(&__r.__d);
|
||||
return (__r.__bits.__reg & __excepts);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
fegetround(void)
|
||||
{
|
||||
union __fpscr __r;
|
||||
|
||||
__mffs(&__r.__d);
|
||||
return (__r.__bits.__reg & _ROUND_MASK);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
fesetround(int __round)
|
||||
{
|
||||
union __fpscr __r;
|
||||
|
||||
if (__round & ~_ROUND_MASK)
|
||||
return (-1);
|
||||
__mffs(&__r.__d);
|
||||
__r.__bits.__reg &= ~_ROUND_MASK;
|
||||
__r.__bits.__reg |= __round;
|
||||
__mtfsf(__r.__d);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
fegetenv(fenv_t *__envp)
|
||||
{
|
||||
union __fpscr __r;
|
||||
|
||||
__mffs(&__r.__d);
|
||||
*__envp = __r.__bits.__reg;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
feholdexcept(fenv_t *__envp)
|
||||
{
|
||||
union __fpscr __r;
|
||||
|
||||
__mffs(&__r.__d);
|
||||
*__envp = __r.__d;
|
||||
__r.__bits.__reg &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
|
||||
__mtfsf(__r.__d);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
fesetenv(const fenv_t *__envp)
|
||||
{
|
||||
union __fpscr __r;
|
||||
|
||||
__r.__bits.__reg = *__envp;
|
||||
__mtfsf(__r.__d);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
feupdateenv(const fenv_t *__envp)
|
||||
{
|
||||
union __fpscr __r;
|
||||
|
||||
__mffs(&__r.__d);
|
||||
__r.__bits.__reg &= FE_ALL_EXCEPT;
|
||||
__r.__bits.__reg |= *__envp;
|
||||
__mtfsf(__r.__d);
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if __BSD_VISIBLE
|
||||
|
||||
static __inline int
|
||||
feenableexcept(int __mask)
|
||||
{
|
||||
union __fpscr __r;
|
||||
fenv_t __oldmask;
|
||||
|
||||
__mffs(&__r.__d);
|
||||
__oldmask = __r.__bits.__reg;
|
||||
__r.__bits.__reg |= (__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT;
|
||||
__mtfsf(__r.__d);
|
||||
return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
fedisableexcept(int __mask)
|
||||
{
|
||||
union __fpscr __r;
|
||||
fenv_t __oldmask;
|
||||
|
||||
__mffs(&__r.__d);
|
||||
__oldmask = __r.__bits.__reg;
|
||||
__r.__bits.__reg &= ~((__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT);
|
||||
__mtfsf(__r.__d);
|
||||
return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
fegetexcept(void)
|
||||
{
|
||||
union __fpscr __r;
|
||||
|
||||
__mffs(&__r.__d);
|
||||
return ((__r.__bits.__reg & _ENABLE_MASK) << _FPUSW_SHIFT);
|
||||
}
|
||||
|
||||
#endif /* __BSD_VISIBLE */
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* !_FENV_H_ */
|
252
headers/posix/arch/x86/fenv.h
Normal file
252
headers/posix/arch/x86/fenv.h
Normal file
@ -0,0 +1,252 @@
|
||||
/*-
|
||||
* 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$
|
||||
*/
|
||||
|
||||
#ifndef _FENV_H_
|
||||
#define _FENV_H_
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
/*
|
||||
* 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 __control;
|
||||
uint16 __mxcsr_hi;
|
||||
uint16 __status;
|
||||
uint16 __mxcsr_lo;
|
||||
uint32 __tag;
|
||||
char __other[16];
|
||||
} fenv_t;
|
||||
|
||||
#define __get_mxcsr(env) (((env).__mxcsr_hi << 16) | \
|
||||
((env).__mxcsr_lo))
|
||||
#define __set_mxcsr(env, x) do { \
|
||||
(env).__mxcsr_hi = (uint32)(x) >> 16; \
|
||||
(env).__mxcsr_lo = (uint16)(x); \
|
||||
} while (0)
|
||||
|
||||
typedef uint16 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)
|
||||
|
||||
/* 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)
|
||||
|
||||
/*
|
||||
* As compared to the x87 control word, the SSE unit's control word
|
||||
* 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
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/* After testing for SSE support once, we cache the result in __has_sse. */
|
||||
enum __sse_support { __SSE_YES, __SSE_NO, __SSE_UNK };
|
||||
extern enum __sse_support __has_sse;
|
||||
int __test_sse(void);
|
||||
#ifdef __SSE__
|
||||
#define __HAS_SSE() 1
|
||||
#else
|
||||
#define __HAS_SSE() (__has_sse == __SSE_YES || \
|
||||
(__has_sse == __SSE_UNK && __test_sse()))
|
||||
#endif
|
||||
|
||||
/* Default floating-point environment */
|
||||
extern const fenv_t __fe_dfl_env;
|
||||
#define FE_DFL_ENV (&__fe_dfl_env)
|
||||
|
||||
#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 __fnclex() __asm __volatile("fnclex")
|
||||
#define __fnstenv(__env) __asm __volatile("fnstenv %0" : "=m" (*(__env)))
|
||||
#define __fnstcw(__cw) __asm __volatile("fnstcw %0" : "=m" (*(__cw)))
|
||||
#define __fnstsw(__sw) __asm __volatile("fnstsw %0" : "=m" (*(__sw)))
|
||||
#define __fwait() __asm __volatile("fwait")
|
||||
#define __ldmxcsr(__csr) __asm __volatile("ldmxcsr %0" : : "m" (__csr))
|
||||
#define __stmxcsr(__csr) __asm __volatile("stmxcsr %0" : "=m" (*(__csr)))
|
||||
|
||||
static __inline int
|
||||
feclearexcept(int __excepts)
|
||||
{
|
||||
fenv_t __env;
|
||||
short __mxcsr;
|
||||
|
||||
if (__excepts == FE_ALL_EXCEPT) {
|
||||
__fnclex();
|
||||
} else {
|
||||
__fnstenv(&__env);
|
||||
__env.__status &= ~__excepts;
|
||||
__fldenv(__env);
|
||||
}
|
||||
if (__HAS_SSE()) {
|
||||
__stmxcsr(&__mxcsr);
|
||||
__mxcsr &= ~__excepts;
|
||||
__ldmxcsr(__mxcsr);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
fegetexceptflag(fexcept_t *__flagp, int __excepts)
|
||||
{
|
||||
int __mxcsr, __status;
|
||||
|
||||
__fnstsw(&__status);
|
||||
if (__HAS_SSE())
|
||||
__stmxcsr(&__mxcsr);
|
||||
else
|
||||
__mxcsr = 0;
|
||||
*__flagp = (__mxcsr | __status) & __excepts;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
|
||||
int feraiseexcept(int __excepts);
|
||||
|
||||
static __inline int
|
||||
fetestexcept(int __excepts)
|
||||
{
|
||||
int __mxcsr, __status;
|
||||
|
||||
__fnstsw(&__status);
|
||||
if (__HAS_SSE())
|
||||
__stmxcsr(&__mxcsr);
|
||||
else
|
||||
__mxcsr = 0;
|
||||
return ((__status | __mxcsr) & __excepts);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
fegetround(void)
|
||||
{
|
||||
int __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);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
fesetround(int __round)
|
||||
{
|
||||
int __mxcsr, __control;
|
||||
|
||||
if (__round & ~_ROUND_MASK)
|
||||
return (-1);
|
||||
|
||||
__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 fegetenv(fenv_t *__envp);
|
||||
int feholdexcept(fenv_t *__envp);
|
||||
|
||||
static __inline int
|
||||
fesetenv(const fenv_t *__envp)
|
||||
{
|
||||
fenv_t __env = *__envp;
|
||||
int __mxcsr;
|
||||
|
||||
__mxcsr = __get_mxcsr(__env);
|
||||
__set_mxcsr(__env, 0xffffffff);
|
||||
/*
|
||||
* 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 feupdateenv(const fenv_t *__envp);
|
||||
|
||||
#if __BSD_VISIBLE
|
||||
|
||||
int feenableexcept(int __mask);
|
||||
int fedisableexcept(int __mask);
|
||||
|
||||
static __inline int
|
||||
fegetexcept(void)
|
||||
{
|
||||
int __control;
|
||||
|
||||
/*
|
||||
* We assume that the masks for the x87 and the SSE unit are
|
||||
* the same.
|
||||
*/
|
||||
__fnstcw(&__control);
|
||||
return (~__control & FE_ALL_EXCEPT);
|
||||
}
|
||||
|
||||
#endif /* __BSD_VISIBLE */
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* !_FENV_H_ */
|
163
headers/posix/arch/x86/npx.h
Normal file
163
headers/posix/arch/x86/npx.h
Normal file
@ -0,0 +1,163 @@
|
||||
/*-
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* William Jolitz.
|
||||
*
|
||||
* 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.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*
|
||||
* from: @(#)npx.h 5.3 (Berkeley) 1/18/91
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* 287/387 NPX Coprocessor Data Structures and Constants
|
||||
* W. Jolitz 1/90
|
||||
*/
|
||||
|
||||
#ifndef _MACHINE_NPX_H_
|
||||
#define _MACHINE_NPX_H_
|
||||
|
||||
#define __aligned(x) __attribute__((__aligned__(x)))
|
||||
|
||||
/* Environment information of floating point unit */
|
||||
struct env87 {
|
||||
long en_cw; /* control word (16bits) */
|
||||
long en_sw; /* status word (16bits) */
|
||||
long en_tw; /* tag word (16bits) */
|
||||
long en_fip; /* floating point instruction pointer */
|
||||
u_short en_fcs; /* floating code segment selector */
|
||||
u_short en_opcode; /* opcode last executed (11 bits ) */
|
||||
long en_foo; /* floating operand offset */
|
||||
long en_fos; /* floating operand segment selector */
|
||||
};
|
||||
|
||||
/* Contents of each floating point accumulator */
|
||||
struct fpacc87 {
|
||||
#ifdef dontdef /* too unportable */
|
||||
u_long fp_mantlo; /* mantissa low (31:0) */
|
||||
u_long fp_manthi; /* mantissa high (63:32) */
|
||||
int fp_exp:15; /* exponent */
|
||||
int fp_sgn:1; /* mantissa sign */
|
||||
#else
|
||||
u_char fp_bytes[10];
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Floating point context */
|
||||
struct save87 {
|
||||
struct env87 sv_env; /* floating point control/status */
|
||||
struct fpacc87 sv_ac[8]; /* accumulator contents, 0-7 */
|
||||
u_char sv_pad0[4]; /* padding for (now unused) saved status word */
|
||||
/*
|
||||
* Bogus padding for emulators. Emulators should use their own
|
||||
* struct and arrange to store into this struct (ending here)
|
||||
* before it is inspected for ptracing or for core dumps. Some
|
||||
* emulators overwrite the whole struct. We have no good way of
|
||||
* knowing how much padding to leave. Leave just enough for the
|
||||
* GPL emulator's i387_union (176 bytes total).
|
||||
*/
|
||||
u_char sv_pad[64]; /* padding; used by emulators */
|
||||
};
|
||||
|
||||
struct envxmm {
|
||||
uint16 en_cw; /* control word (16bits) */
|
||||
uint16 en_sw; /* status word (16bits) */
|
||||
uint16 en_tw; /* tag word (16bits) */
|
||||
uint16 en_opcode; /* opcode last executed (11 bits ) */
|
||||
uint32 en_fip; /* floating point instruction pointer */
|
||||
uint16 en_fcs; /* floating code segment selector */
|
||||
uint16 en_pad0; /* padding */
|
||||
uint32 en_foo; /* floating operand offset */
|
||||
uint16 en_fos; /* floating operand segment selector */
|
||||
uint16 en_pad1; /* padding */
|
||||
uint32 en_mxcsr; /* SSE control/status register */
|
||||
uint32 en_mxcsr_mask; /* valid bits in mxcsr */
|
||||
};
|
||||
|
||||
/* Contents of each SSE extended accumulator */
|
||||
struct xmmacc {
|
||||
u_char xmm_bytes[16];
|
||||
};
|
||||
|
||||
struct savexmm {
|
||||
struct envxmm sv_env;
|
||||
struct {
|
||||
struct fpacc87 fp_acc;
|
||||
u_char fp_pad[6]; /* padding */
|
||||
} sv_fp[8];
|
||||
struct xmmacc sv_xmm[8];
|
||||
u_char sv_pad[224];
|
||||
} __aligned(16);
|
||||
|
||||
union savefpu {
|
||||
struct save87 sv_87;
|
||||
struct savexmm sv_xmm;
|
||||
};
|
||||
|
||||
/*
|
||||
* The hardware default control word for i387's and later coprocessors is
|
||||
* 0x37F, giving:
|
||||
*
|
||||
* round to nearest
|
||||
* 64-bit precision
|
||||
* all exceptions masked.
|
||||
*
|
||||
* We modify the affine mode bit and precision bits in this to give:
|
||||
*
|
||||
* affine mode for 287's (if they work at all) (1 in bitfield 1<<12)
|
||||
* 53-bit precision (2 in bitfield 3<<8)
|
||||
*
|
||||
* 64-bit precision often gives bad results with high level languages
|
||||
* because it makes the results of calculations depend on whether
|
||||
* intermediate values are stored in memory or in FPU registers.
|
||||
*/
|
||||
#define __INITIAL_NPXCW__ 0x127F
|
||||
#define __INITIAL_MXCSR__ 0x1F80
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#define IO_NPX 0x0F0 /* Numeric Coprocessor */
|
||||
#define IO_NPXSIZE 16 /* 80387/80487 NPX registers */
|
||||
|
||||
#define IRQ_NPX 13
|
||||
|
||||
/* full reset on some systems, NOP on others */
|
||||
#define npx_full_reset() outb(IO_NPX + 1, 0)
|
||||
|
||||
int npxdna(void);
|
||||
void npxdrop(void);
|
||||
void npxexit(struct thread *td);
|
||||
int npxformat(void);
|
||||
int npxgetregs(struct thread *td, union savefpu *addr);
|
||||
void npxinit(void);
|
||||
void npxsave(union savefpu *addr);
|
||||
void npxsetregs(struct thread *td, union savefpu *addr);
|
||||
int npxtrap(void);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !_MACHINE_NPX_H_ */
|
15
headers/posix/fenv.h
Normal file
15
headers/posix/fenv.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef _FENV_H
|
||||
#define _FENV_H
|
||||
|
||||
#if defined(_X86_)
|
||||
# include <arch/x86/fenv.h>
|
||||
#elif defined(__ARM__)
|
||||
# include <arch/arm/fenv.h>
|
||||
#elif defined(__POWERPC__)
|
||||
# include <arch/ppc/fenv.h>
|
||||
#else
|
||||
# error There is no fenv.h for this architecture!
|
||||
#endif
|
||||
|
||||
#endif /* _FENV_H */
|
||||
|
@ -15,6 +15,7 @@ local librootObjects =
|
||||
posix_crypt.o
|
||||
posix_locale.o
|
||||
posix_main.o
|
||||
posix_fenv.o
|
||||
posix_pthread.o
|
||||
posix_signal.o
|
||||
posix_stdio.o
|
||||
|
@ -30,6 +30,17 @@ MergeObject posix_main.o :
|
||||
utime.c
|
||||
;
|
||||
|
||||
if $(TARGET_ARCH) = x86 {
|
||||
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src system libroot posix fenv i387 ] ;
|
||||
} else if $(TARGET_ARCH) = ppc {
|
||||
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src system libroot posix fenv powerpc ] ;
|
||||
} else if $(TARGET_ARCH) = arm {
|
||||
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src system libroot posix fenv arm ] ;
|
||||
}
|
||||
MergeObject posix_fenv.o :
|
||||
fenv.c
|
||||
;
|
||||
|
||||
SubInclude HAIKU_TOP src system libroot posix arch $(TARGET_ARCH) ;
|
||||
|
||||
SubInclude HAIKU_TOP src system libroot posix crypt ;
|
||||
|
35
src/system/libroot/posix/fenv/arm/fenv.c
Normal file
35
src/system/libroot/posix/fenv/arm/fenv.c
Normal file
@ -0,0 +1,35 @@
|
||||
/*-
|
||||
* Copyright (c) 2004 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$
|
||||
*/
|
||||
|
||||
#include <posix/fenv.h>
|
||||
|
||||
/*
|
||||
* Hopefully the system ID byte is immutable, so it's valid to use
|
||||
* this as a default environment.
|
||||
*/
|
||||
const fenv_t __fe_dfl_env = 0;
|
211
src/system/libroot/posix/fenv/i387/fenv.c
Normal file
211
src/system/libroot/posix/fenv/i387/fenv.c
Normal file
@ -0,0 +1,211 @@
|
||||
/*-
|
||||
* 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$
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
#include <SupportDefs.h>
|
||||
#include <arch/x86/npx.h>
|
||||
#include <posix/fenv.h>
|
||||
|
||||
const fenv_t __fe_dfl_env = {
|
||||
__INITIAL_NPXCW__,
|
||||
0x0000,
|
||||
0x0000,
|
||||
0x1f80,
|
||||
0xffffffff,
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff }
|
||||
};
|
||||
|
||||
enum __sse_support __has_sse =
|
||||
#ifdef __SSE__
|
||||
__SSE_YES;
|
||||
#else
|
||||
__SSE_UNK;
|
||||
#endif
|
||||
|
||||
#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
|
||||
* we need to use ldmxcsr/stmxcsr to get correct results if any part
|
||||
* of the program was compiled to use SSE floating-point, but we can't
|
||||
* use SSE on older processors.
|
||||
*/
|
||||
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
|
||||
fesetexceptflag(const fexcept_t *flagp, int excepts)
|
||||
{
|
||||
fenv_t env;
|
||||
int mxcsr;
|
||||
|
||||
__fnstenv(&env);
|
||||
env.__status &= ~excepts;
|
||||
env.__status |= *flagp & excepts;
|
||||
__fldenv(env);
|
||||
|
||||
if (__HAS_SSE()) {
|
||||
__stmxcsr(&mxcsr);
|
||||
mxcsr &= ~excepts;
|
||||
mxcsr |= *flagp & excepts;
|
||||
__ldmxcsr(mxcsr);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
feraiseexcept(int excepts)
|
||||
{
|
||||
fexcept_t ex = excepts;
|
||||
|
||||
fesetexceptflag(&ex, excepts);
|
||||
__fwait();
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
fegetenv(fenv_t *envp)
|
||||
{
|
||||
int 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);
|
||||
__set_mxcsr(*envp, mxcsr);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
feholdexcept(fenv_t *envp)
|
||||
{
|
||||
int mxcsr;
|
||||
|
||||
__fnstenv(envp);
|
||||
__fnclex();
|
||||
if (__HAS_SSE()) {
|
||||
__stmxcsr(&mxcsr);
|
||||
__set_mxcsr(*envp, mxcsr);
|
||||
mxcsr &= ~FE_ALL_EXCEPT;
|
||||
mxcsr |= FE_ALL_EXCEPT << _SSE_EMASK_SHIFT;
|
||||
__ldmxcsr(mxcsr);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
feupdateenv(const fenv_t *envp)
|
||||
{
|
||||
int mxcsr, 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)
|
||||
{
|
||||
int mxcsr, 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;
|
||||
control &= ~mask;
|
||||
__fldcw(control);
|
||||
if (__HAS_SSE()) {
|
||||
mxcsr &= ~(mask << _SSE_EMASK_SHIFT);
|
||||
__ldmxcsr(mxcsr);
|
||||
}
|
||||
return (~omask);
|
||||
}
|
||||
|
||||
int
|
||||
__fedisableexcept(int mask)
|
||||
{
|
||||
int mxcsr, 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;
|
||||
control |= mask;
|
||||
__fldcw(control);
|
||||
if (__HAS_SSE()) {
|
||||
mxcsr |= mask << _SSE_EMASK_SHIFT;
|
||||
__ldmxcsr(mxcsr);
|
||||
}
|
||||
return (~omask);
|
||||
}
|
||||
|
||||
__weak_reference(__feenableexcept, feenableexcept);
|
||||
__weak_reference(__fedisableexcept, fedisableexcept);
|
31
src/system/libroot/posix/fenv/powerpc/fenv.c
Normal file
31
src/system/libroot/posix/fenv/powerpc/fenv.c
Normal file
@ -0,0 +1,31 @@
|
||||
/*-
|
||||
* Copyright (c) 2004 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$
|
||||
*/
|
||||
|
||||
#include <posix/fenv.h>
|
||||
|
||||
const fenv_t __fe_dfl_env = 0x00000000;
|
Loading…
Reference in New Issue
Block a user