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:
Artur Wyszynski 2010-02-09 06:09:28 +00:00
parent 5fb7d0a580
commit 38ecc1a764
10 changed files with 1206 additions and 0 deletions

View 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_ */

View 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_ */

View 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_ */

View 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
View 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 */

View File

@ -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

View File

@ -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 ;

View 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;

View 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);

View 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;