fenv.h revision 0933a70e3aa803a8762855b5b5ad591b03722075
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync/** @file
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync * innotek Portable Runtime / No-CRT - fenv.h, AMD64.
5b281ba489ca18f0380d7efc7a5108b606cce449vboxsync */
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync/*
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync * Copyright (C) 2006-2007 innotek GmbH
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync *
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync * available from http://www.virtualbox.org. This file is free software;
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync * you can redistribute it and/or modify it under the terms of the GNU
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync * General Public License as published by the Free Software Foundation,
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * --------------------------------------------------------------------
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync *
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * This code is based on:
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync *
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * All rights reserved.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync *
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Redistribution and use in source and binary forms, with or without
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * modification, are permitted provided that the following conditions
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * are met:
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync * 1. Redistributions of source code must retain the above copyright
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync * notice, this list of conditions and the following disclaimer.
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync * 2. Redistributions in binary form must reproduce the above copyright
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync * notice, this list of conditions and the following disclaimer in the
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync * documentation and/or other materials provided with the distribution.
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync *
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7d6e0aa02bf89fa403a13d5eac18a18b5a79893fvboxsync * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
6473a6585394a0255de9936152f2fd35d068b347vboxsync * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync * SUCH DAMAGE.
7d6e0aa02bf89fa403a13d5eac18a18b5a79893fvboxsync */
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync
f4db180328f833f9fc9cb07a1a4a0bc948a47afevboxsync#ifndef ___iprt_nocrt_amd64_fenv_h
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync#define ___iprt_nocrt_amd64_fenv_h
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync#include <iprt/types.h>
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync
7995839c0b791ae2334df998d34dbccac12b3b41vboxsynctypedef struct {
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync struct {
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync uint32_t __control;
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync uint32_t __status;
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync uint32_t __tag;
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync char __other[16];
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync } __x87;
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync uint32_t __mxcsr;
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync} fenv_t;
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsynctypedef uint16_t fexcept_t;
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync/* Exception flags */
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync#define FE_INVALID 0x01
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync#define FE_DENORMAL 0x02
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync#define FE_DIVBYZERO 0x04
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync#define FE_OVERFLOW 0x08
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync#define FE_UNDERFLOW 0x10
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync#define FE_INEXACT 0x20
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_DENORMAL | FE_INEXACT | \
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync/* Rounding modes */
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync#define FE_TONEAREST 0x0000
3a109c62545ec1a0ebca5c8c3e5e9b88d3c7b672vboxsync#define FE_DOWNWARD 0x0400
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync#define FE_UPWARD 0x0800
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync#define FE_TOWARDZERO 0x0c00
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync FE_UPWARD | FE_TOWARDZERO)
3a109c62545ec1a0ebca5c8c3e5e9b88d3c7b672vboxsync
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync/*
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync * As compared to the x87 control word, the SSE unit's control word
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync * has the rounding control bits offset by 3 and the exception mask
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync * bits offset by 7.
3a109c62545ec1a0ebca5c8c3e5e9b88d3c7b672vboxsync */
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync#define _SSE_ROUND_SHIFT 3
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync#define _SSE_EMASK_SHIFT 7
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync__BEGIN_DECLS
3a109c62545ec1a0ebca5c8c3e5e9b88d3c7b672vboxsync
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync/* Default floating-point environment */
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsyncextern const fenv_t RT_NOCRT(__fe_dfl_env);
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync#define FE_DFL_ENV (&__fe_dfl_env)
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync#define __fldcw(__cw) __asm __volatile("fldcw %0" : : "m" (__cw))
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync#define __fldenv(__env) __asm __volatile("fldenv %0" : : "m" (__env))
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync#define __fnclex() __asm __volatile("fnclex")
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync#define __fnstenv(__env) __asm __volatile("fnstenv %0" : "=m" (*(__env)))
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync#define __fnstcw(__cw) __asm __volatile("fnstcw %0" : "=m" (*(__cw)))
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync#define __fnstsw(__sw) __asm __volatile("fnstsw %0" : "=am" (*(__sw)))
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync#define __fwait() __asm __volatile("fwait")
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync#define __ldmxcsr(__csr) __asm __volatile("ldmxcsr %0" : : "m" (__csr))
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync#define __stmxcsr(__csr) __asm __volatile("stmxcsr %0" : "=m" (*(__csr)))
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync
7995839c0b791ae2334df998d34dbccac12b3b41vboxsyncDECLINLINE(int)
7995839c0b791ae2334df998d34dbccac12b3b41vboxsyncfeclearexcept(int __excepts)
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync{
da41353d6837bbc94e31da46f0698be45c106305vboxsync fenv_t __env;
da41353d6837bbc94e31da46f0698be45c106305vboxsync
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync if (__excepts == FE_ALL_EXCEPT) {
da41353d6837bbc94e31da46f0698be45c106305vboxsync __fnclex();
e1cda3b0b3faa83df2fe0bf69e6938a6e7c4cb20vboxsync } else {
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync __fnstenv(&__env.__x87);
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync __env.__x87.__status &= ~__excepts;
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync __fldenv(__env.__x87);
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync }
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync __stmxcsr(&__env.__mxcsr);
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync __env.__mxcsr &= ~__excepts;
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync __ldmxcsr(__env.__mxcsr);
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync return (0);
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync}
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync
7995839c0b791ae2334df998d34dbccac12b3b41vboxsyncDECLINLINE(int)
7995839c0b791ae2334df998d34dbccac12b3b41vboxsyncfegetexceptflag(fexcept_t *__flagp, int __excepts)
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync{
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync int __mxcsr, __status;
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync __stmxcsr(&__mxcsr);
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync __fnstsw(&__status);
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync *__flagp = (__mxcsr | __status) & __excepts;
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync return (0);
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync}
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync
7995839c0b791ae2334df998d34dbccac12b3b41vboxsyncint RT_NOCRT(fesetexceptflag)(const fexcept_t *__flagp, int __excepts);
7995839c0b791ae2334df998d34dbccac12b3b41vboxsyncint RT_NOCRT(feraiseexcept)(int __excepts);
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync
7995839c0b791ae2334df998d34dbccac12b3b41vboxsyncDECLINLINE(int)
7995839c0b791ae2334df998d34dbccac12b3b41vboxsyncfetestexcept(int __excepts)
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync{
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync int __mxcsr, __status;
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync __stmxcsr(&__mxcsr);
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync __fnstsw(&__status);
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync return ((__status | __mxcsr) & __excepts);
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync}
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync
7995839c0b791ae2334df998d34dbccac12b3b41vboxsyncDECLINLINE(int)
7995839c0b791ae2334df998d34dbccac12b3b41vboxsyncfegetround(void)
1fb61f986d9f400eb3cc440422475f0fee5f96advboxsync{
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync int __control;
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync /*
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync * We assume that the x87 and the SSE unit agree on the
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync * rounding mode. Reading the control word on the x87 turns
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync * out to be about 5 times faster than reading it on the SSE
7995839c0b791ae2334df998d34dbccac12b3b41vboxsync * unit on an Opteron 244.
*/
__fnstcw(&__control);
return (__control & _ROUND_MASK);
}
DECLINLINE(int)
fesetround(int __round)
{
int __mxcsr, __control;
if (__round & ~_ROUND_MASK)
return (-1);
__fnstcw(&__control);
__control &= ~_ROUND_MASK;
__control |= __round;
__fldcw(__control);
__stmxcsr(&__mxcsr);
__mxcsr &= ~(_ROUND_MASK << _SSE_ROUND_SHIFT);
__mxcsr |= __round << _SSE_ROUND_SHIFT;
__ldmxcsr(__mxcsr);
return (0);
}
int RT_NOCRT(fegetenv)(fenv_t *__envp);
int RT_NOCRT(feholdexcept)(fenv_t *__envp);
DECLINLINE(int)
fesetenv(const fenv_t *__envp)
{
__fldenv(__envp->__x87);
__ldmxcsr(__envp->__mxcsr);
return (0);
}
int RT_NOCRT(feupdateenv)(const fenv_t *__envp);
int RT_NOCRT(feenableexcept)(int __mask);
int RT_NOCRT(fedisableexcept)(int __mask);
DECLINLINE(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);
}
__END_DECLS
#ifndef RT_WITHOUT_NOCRT_WRAPPERS
# define fesetexceptflag RT_NOCRT(fesetexceptflag)
# define feraiseexcept RT_NOCRT(feraiseexcept)
# define fegetenv RT_NOCRT(fegetenv)
# define feholdexcept RT_NOCRT(feholdexcept)
# define feupdateenv RT_NOCRT(feupdateenv)
# define feenableexcept RT_NOCRT(feenableexcept)
# define fedisableexcept RT_NOCRT(fedisableexcept)
# define __fe_dfl_env RT_NOCRT(__fe_dfl_env)
#endif
#endif /* !__iprt_nocrt_amd64_fenv_h__ */