Commit 34422eb5 authored by Alexandre Julliard's avatar Alexandre Julliard

msvcrt: Move the fenv_t definition to the public header.

parent 1f11f41f
...@@ -148,12 +148,6 @@ struct MSVCRT_lconv ...@@ -148,12 +148,6 @@ struct MSVCRT_lconv
typedef struct typedef struct
{ {
unsigned int control;
unsigned int status;
} fenv_t;
typedef struct
{
double r; double r;
double i; double i;
} _Dcomplex; } _Dcomplex;
...@@ -798,13 +792,13 @@ static void test_feenv(void) ...@@ -798,13 +792,13 @@ static void test_feenv(void)
ret = p_fegetenv(&env); ret = p_fegetenv(&env);
ok(!ret, "fegetenv returned %x\n", ret); ok(!ret, "fegetenv returned %x\n", ret);
p_fesetround(FE_UPWARD); p_fesetround(FE_UPWARD);
ok(env.control == (_EM_INEXACT|_EM_UNDERFLOW|_EM_OVERFLOW|_EM_ZERODIVIDE|_EM_INVALID), ok(env._Fe_ctl == (_EM_INEXACT|_EM_UNDERFLOW|_EM_OVERFLOW|_EM_ZERODIVIDE|_EM_INVALID),
"env.control = %x\n", env.control); "env._Fe_ctl = %lx\n", env._Fe_ctl);
ok(!env.status, "env.status = %x\n", env.status); ok(!env._Fe_stat, "env._Fe_stat = %lx\n", env._Fe_stat);
ret = p_fegetenv(&env2); ret = p_fegetenv(&env2);
ok(!ret, "fegetenv returned %x\n", ret); ok(!ret, "fegetenv returned %x\n", ret);
ok(env2.control == (_EM_INEXACT|_EM_UNDERFLOW|_EM_OVERFLOW|_EM_ZERODIVIDE|_EM_INVALID | FE_UPWARD), ok(env2._Fe_ctl == (_EM_INEXACT|_EM_UNDERFLOW|_EM_OVERFLOW|_EM_ZERODIVIDE|_EM_INVALID | FE_UPWARD),
"env2.control = %x\n", env2.control); "env2._Fe_ctl = %lx\n", env2._Fe_ctl);
ret = p_fesetenv(&env); ret = p_fesetenv(&env);
ok(!ret, "fesetenv returned %x\n", ret); ok(!ret, "fesetenv returned %x\n", ret);
ret = p_fegetround(); ret = p_fegetround();
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <stdio.h> #include <stdio.h>
#include <fenv.h>
#include <fpieee.h> #include <fpieee.h>
#include <math.h> #include <math.h>
...@@ -2065,11 +2066,11 @@ int CDECL _controlfp_s(unsigned int *cur, unsigned int newval, unsigned int mask ...@@ -2065,11 +2066,11 @@ int CDECL _controlfp_s(unsigned int *cur, unsigned int newval, unsigned int mask
/********************************************************************* /*********************************************************************
* fegetenv (MSVCR120.@) * fegetenv (MSVCR120.@)
*/ */
int CDECL MSVCRT_fegetenv(MSVCRT_fenv_t *env) int CDECL MSVCRT_fegetenv(fenv_t *env)
{ {
env->control = _controlfp(0, 0) & (MSVCRT__EM_INEXACT | MSVCRT__EM_UNDERFLOW | env->_Fe_ctl = _controlfp(0, 0) & (MSVCRT__EM_INEXACT | MSVCRT__EM_UNDERFLOW |
MSVCRT__EM_OVERFLOW | MSVCRT__EM_ZERODIVIDE | MSVCRT__EM_INVALID | MSVCRT__RC_CHOP); MSVCRT__EM_OVERFLOW | MSVCRT__EM_ZERODIVIDE | MSVCRT__EM_INVALID | MSVCRT__RC_CHOP);
env->status = _statusfp(); env->_Fe_stat = _statusfp();
return 0; return 0;
} }
#endif #endif
...@@ -2160,7 +2161,7 @@ void CDECL _fpreset(void) ...@@ -2160,7 +2161,7 @@ void CDECL _fpreset(void)
/********************************************************************* /*********************************************************************
* fesetenv (MSVCR120.@) * fesetenv (MSVCR120.@)
*/ */
int CDECL MSVCRT_fesetenv(const MSVCRT_fenv_t *env) int CDECL MSVCRT_fesetenv(const fenv_t *env)
{ {
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
struct { struct {
...@@ -2180,7 +2181,7 @@ int CDECL MSVCRT_fesetenv(const MSVCRT_fenv_t *env) ...@@ -2180,7 +2181,7 @@ int CDECL MSVCRT_fesetenv(const MSVCRT_fenv_t *env)
TRACE( "(%p)\n", env ); TRACE( "(%p)\n", env );
if (!env->control && !env->status) { if (!env->_Fe_ctl && !env->_Fe_stat) {
_fpreset(); _fpreset();
return 0; return 0;
} }
...@@ -2188,12 +2189,12 @@ int CDECL MSVCRT_fesetenv(const MSVCRT_fenv_t *env) ...@@ -2188,12 +2189,12 @@ int CDECL MSVCRT_fesetenv(const MSVCRT_fenv_t *env)
__asm__ __volatile__( "fnstenv %0" : "=m" (fenv) ); __asm__ __volatile__( "fnstenv %0" : "=m" (fenv) );
fenv.control_word &= ~0xc3d; fenv.control_word &= ~0xc3d;
if (env->control & MSVCRT__EM_INVALID) fenv.control_word |= 0x1; if (env->_Fe_ctl & MSVCRT__EM_INVALID) fenv.control_word |= 0x1;
if (env->control & MSVCRT__EM_ZERODIVIDE) fenv.control_word |= 0x4; if (env->_Fe_ctl & MSVCRT__EM_ZERODIVIDE) fenv.control_word |= 0x4;
if (env->control & MSVCRT__EM_OVERFLOW) fenv.control_word |= 0x8; if (env->_Fe_ctl & MSVCRT__EM_OVERFLOW) fenv.control_word |= 0x8;
if (env->control & MSVCRT__EM_UNDERFLOW) fenv.control_word |= 0x10; if (env->_Fe_ctl & MSVCRT__EM_UNDERFLOW) fenv.control_word |= 0x10;
if (env->control & MSVCRT__EM_INEXACT) fenv.control_word |= 0x20; if (env->_Fe_ctl & MSVCRT__EM_INEXACT) fenv.control_word |= 0x20;
switch (env->control & MSVCRT__MCW_RC) switch (env->_Fe_ctl & MSVCRT__MCW_RC)
{ {
case MSVCRT__RC_UP|MSVCRT__RC_DOWN: fenv.control_word |= 0xc00; break; case MSVCRT__RC_UP|MSVCRT__RC_DOWN: fenv.control_word |= 0xc00; break;
case MSVCRT__RC_UP: fenv.control_word |= 0x800; break; case MSVCRT__RC_UP: fenv.control_word |= 0x800; break;
...@@ -2201,11 +2202,11 @@ int CDECL MSVCRT_fesetenv(const MSVCRT_fenv_t *env) ...@@ -2201,11 +2202,11 @@ int CDECL MSVCRT_fesetenv(const MSVCRT_fenv_t *env)
} }
fenv.status_word &= ~0x3d; fenv.status_word &= ~0x3d;
if (env->status & MSVCRT__SW_INVALID) fenv.status_word |= 0x1; if (env->_Fe_stat & FE_INVALID) fenv.status_word |= 0x1;
if (env->status & MSVCRT__SW_ZERODIVIDE) fenv.status_word |= 0x4; if (env->_Fe_stat & FE_DIVBYZERO) fenv.status_word |= 0x4;
if (env->status & MSVCRT__SW_OVERFLOW) fenv.status_word |= 0x8; if (env->_Fe_stat & FE_OVERFLOW) fenv.status_word |= 0x8;
if (env->status & MSVCRT__SW_UNDERFLOW) fenv.status_word |= 0x10; if (env->_Fe_stat & FE_UNDERFLOW) fenv.status_word |= 0x10;
if (env->status & MSVCRT__SW_INEXACT) fenv.status_word |= 0x20; if (env->_Fe_stat & FE_INEXACT) fenv.status_word |= 0x20;
__asm__ __volatile__( "fldenv %0" : : "m" (fenv) : "st", "st(1)", __asm__ __volatile__( "fldenv %0" : : "m" (fenv) : "st", "st(1)",
"st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)" ); "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)" );
...@@ -2215,12 +2216,12 @@ int CDECL MSVCRT_fesetenv(const MSVCRT_fenv_t *env) ...@@ -2215,12 +2216,12 @@ int CDECL MSVCRT_fesetenv(const MSVCRT_fenv_t *env)
DWORD fpword; DWORD fpword;
__asm__ __volatile__( "stmxcsr %0" : "=m" (fpword) ); __asm__ __volatile__( "stmxcsr %0" : "=m" (fpword) );
fpword &= ~0x7e80; fpword &= ~0x7e80;
if (env->control & MSVCRT__EM_INVALID) fpword |= 0x80; if (env->_Fe_ctl & MSVCRT__EM_INVALID) fpword |= 0x80;
if (env->control & MSVCRT__EM_ZERODIVIDE) fpword |= 0x200; if (env->_Fe_ctl & MSVCRT__EM_ZERODIVIDE) fpword |= 0x200;
if (env->control & MSVCRT__EM_OVERFLOW) fpword |= 0x400; if (env->_Fe_ctl & MSVCRT__EM_OVERFLOW) fpword |= 0x400;
if (env->control & MSVCRT__EM_UNDERFLOW) fpword |= 0x800; if (env->_Fe_ctl & MSVCRT__EM_UNDERFLOW) fpword |= 0x800;
if (env->control & MSVCRT__EM_INEXACT) fpword |= 0x1000; if (env->_Fe_ctl & MSVCRT__EM_INEXACT) fpword |= 0x1000;
switch (env->control & MSVCRT__MCW_RC) switch (env->_Fe_ctl & MSVCRT__MCW_RC)
{ {
case MSVCRT__RC_CHOP: fpword |= 0x6000; break; case MSVCRT__RC_CHOP: fpword |= 0x6000; break;
case MSVCRT__RC_UP: fpword |= 0x4000; break; case MSVCRT__RC_UP: fpword |= 0x4000; break;
...@@ -3833,11 +3834,11 @@ double CDECL MSVCR120_acosh(double x) ...@@ -3833,11 +3834,11 @@ double CDECL MSVCR120_acosh(double x)
{ {
if (x < 1) if (x < 1)
{ {
MSVCRT_fenv_t env; fenv_t env;
*MSVCRT__errno() = MSVCRT_EDOM; *MSVCRT__errno() = MSVCRT_EDOM;
MSVCRT_fegetenv(&env); MSVCRT_fegetenv(&env);
env.status |= MSVCRT__SW_INVALID; env._Fe_stat |= FE_INVALID;
MSVCRT_fesetenv(&env); MSVCRT_fesetenv(&env);
return NAN; return NAN;
} }
...@@ -3851,11 +3852,11 @@ float CDECL MSVCR120_acoshf(float x) ...@@ -3851,11 +3852,11 @@ float CDECL MSVCR120_acoshf(float x)
{ {
if (x < 1) if (x < 1)
{ {
MSVCRT_fenv_t env; fenv_t env;
*MSVCRT__errno() = MSVCRT_EDOM; *MSVCRT__errno() = MSVCRT_EDOM;
MSVCRT_fegetenv(&env); MSVCRT_fegetenv(&env);
env.status |= MSVCRT__SW_INVALID; env._Fe_stat |= FE_INVALID;
MSVCRT_fesetenv(&env); MSVCRT_fesetenv(&env);
return NAN; return NAN;
} }
...@@ -3878,13 +3879,13 @@ double CDECL MSVCR120_atanh(double x) ...@@ -3878,13 +3879,13 @@ double CDECL MSVCR120_atanh(double x)
double ret; double ret;
if (x > 1 || x < -1) { if (x > 1 || x < -1) {
MSVCRT_fenv_t env; fenv_t env;
*MSVCRT__errno() = MSVCRT_EDOM; *MSVCRT__errno() = MSVCRT_EDOM;
/* on Linux atanh returns -NAN in this case */ /* on Linux atanh returns -NAN in this case */
MSVCRT_fegetenv(&env); MSVCRT_fegetenv(&env);
env.status |= MSVCRT__SW_INVALID; env._Fe_stat |= FE_INVALID;
MSVCRT_fesetenv(&env); MSVCRT_fesetenv(&env);
return NAN; return NAN;
} }
...@@ -3902,12 +3903,12 @@ float CDECL MSVCR120_atanhf(float x) ...@@ -3902,12 +3903,12 @@ float CDECL MSVCR120_atanhf(float x)
float ret; float ret;
if (x > 1 || x < -1) { if (x > 1 || x < -1) {
MSVCRT_fenv_t env; fenv_t env;
*MSVCRT__errno() = MSVCRT_EDOM; *MSVCRT__errno() = MSVCRT_EDOM;
MSVCRT_fegetenv(&env); MSVCRT_fegetenv(&env);
env.status |= MSVCRT__SW_INVALID; env._Fe_stat |= FE_INVALID;
MSVCRT_fesetenv(&env); MSVCRT_fesetenv(&env);
return NAN; return NAN;
} }
...@@ -4084,7 +4085,7 @@ double CDECL _except1(DWORD fpe, _FP_OPERATION_CODE op, double arg, double res, ...@@ -4084,7 +4085,7 @@ double CDECL _except1(DWORD fpe, _FP_OPERATION_CODE op, double arg, double res,
{ {
ULONG_PTR exception_arg; ULONG_PTR exception_arg;
DWORD exception = 0; DWORD exception = 0;
MSVCRT_fenv_t env; fenv_t env;
DWORD fpword = 0; DWORD fpword = 0;
WORD operation; WORD operation;
...@@ -4101,43 +4102,43 @@ double CDECL _except1(DWORD fpe, _FP_OPERATION_CODE op, double arg, double res, ...@@ -4101,43 +4102,43 @@ double CDECL _except1(DWORD fpe, _FP_OPERATION_CODE op, double arg, double res,
if (fpe & 0x1) { /* overflow */ if (fpe & 0x1) { /* overflow */
if ((fpe == 0x1 && (cw & 0x8)) || (fpe==0x11 && (cw & 0x28))) { if ((fpe == 0x1 && (cw & 0x8)) || (fpe==0x11 && (cw & 0x28))) {
/* 32-bit version also sets SW_INEXACT here */ /* 32-bit version also sets SW_INEXACT here */
env.status |= MSVCRT__SW_OVERFLOW; env._Fe_stat |= FE_OVERFLOW;
if (fpe & 0x10) env.status |= MSVCRT__SW_INEXACT; if (fpe & 0x10) env._Fe_stat |= FE_INEXACT;
res = signbit(res) ? -INFINITY : INFINITY; res = signbit(res) ? -INFINITY : INFINITY;
} else { } else {
exception = EXCEPTION_FLT_OVERFLOW; exception = EXCEPTION_FLT_OVERFLOW;
} }
} else if (fpe & 0x2) { /* underflow */ } else if (fpe & 0x2) { /* underflow */
if ((fpe == 0x2 && (cw & 0x10)) || (fpe==0x12 && (cw & 0x30))) { if ((fpe == 0x2 && (cw & 0x10)) || (fpe==0x12 && (cw & 0x30))) {
env.status |= MSVCRT__SW_UNDERFLOW; env._Fe_stat |= FE_UNDERFLOW;
if (fpe & 0x10) env.status |= MSVCRT__SW_INEXACT; if (fpe & 0x10) env._Fe_stat |= FE_INEXACT;
res = signbit(res) ? -0.0 : 0.0; res = signbit(res) ? -0.0 : 0.0;
} else { } else {
exception = EXCEPTION_FLT_UNDERFLOW; exception = EXCEPTION_FLT_UNDERFLOW;
} }
} else if (fpe & 0x4) { /* zerodivide */ } else if (fpe & 0x4) { /* zerodivide */
if ((fpe == 0x4 && (cw & 0x4)) || (fpe==0x14 && (cw & 0x24))) { if ((fpe == 0x4 && (cw & 0x4)) || (fpe==0x14 && (cw & 0x24))) {
env.status |= MSVCRT__SW_ZERODIVIDE; env._Fe_stat |= FE_DIVBYZERO;
if (fpe & 0x10) env.status |= MSVCRT__SW_INEXACT; if (fpe & 0x10) env._Fe_stat |= FE_INEXACT;
} else { } else {
exception = EXCEPTION_FLT_DIVIDE_BY_ZERO; exception = EXCEPTION_FLT_DIVIDE_BY_ZERO;
} }
} else if (fpe & 0x8) { /* invalid */ } else if (fpe & 0x8) { /* invalid */
if (fpe == 0x8 && (cw & 0x1)) { if (fpe == 0x8 && (cw & 0x1)) {
env.status |= MSVCRT__SW_INVALID; env._Fe_stat |= FE_INVALID;
} else { } else {
exception = EXCEPTION_FLT_INVALID_OPERATION; exception = EXCEPTION_FLT_INVALID_OPERATION;
} }
} else if (fpe & 0x10) { /* inexact */ } else if (fpe & 0x10) { /* inexact */
if (fpe == 0x10 && (cw & 0x20)) { if (fpe == 0x10 && (cw & 0x20)) {
env.status |= MSVCRT__SW_INEXACT; env._Fe_stat |= FE_INEXACT;
} else { } else {
exception = EXCEPTION_FLT_INEXACT_RESULT; exception = EXCEPTION_FLT_INEXACT_RESULT;
} }
} }
if (exception) if (exception)
env.status = 0; env._Fe_stat = 0;
MSVCRT_fesetenv(&env); MSVCRT_fesetenv(&env);
if (exception) if (exception)
RaiseException(exception, 0, 1, &exception_arg); RaiseException(exception, 0, 1, &exception_arg);
......
...@@ -985,12 +985,6 @@ struct MSVCRT__stat64 { ...@@ -985,12 +985,6 @@ struct MSVCRT__stat64 {
#define MSVCRT__DN_SAVE_OPERANDS_FLUSH_RESULTS 0x03000000 #define MSVCRT__DN_SAVE_OPERANDS_FLUSH_RESULTS 0x03000000
#define MSVCRT__EM_AMBIGUOUS 0x80000000 #define MSVCRT__EM_AMBIGUOUS 0x80000000
typedef struct
{
unsigned int control;
unsigned int status;
} MSVCRT_fenv_t;
#define MSVCRT_CLOCKS_PER_SEC 1000 #define MSVCRT_CLOCKS_PER_SEC 1000
/* signals */ /* signals */
......
...@@ -13,10 +13,26 @@ ...@@ -13,10 +13,26 @@
#define FE_DOWNWARD _RC_DOWN #define FE_DOWNWARD _RC_DOWN
#define FE_TOWARDZERO _RC_CHOP #define FE_TOWARDZERO _RC_CHOP
#define FE_INEXACT _SW_INEXACT
#define FE_UNDERFLOW _SW_UNDERFLOW
#define FE_OVERFLOW _SW_OVERFLOW
#define FE_DIVBYZERO _SW_ZERODIVIDE
#define FE_INVALID _SW_INVALID
#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
typedef struct
{
__msvcrt_ulong _Fe_ctl;
__msvcrt_ulong _Fe_stat;
} fenv_t;
_ACRTIMP int __cdecl fegetenv(fenv_t*);
_ACRTIMP int __cdecl fesetenv(const fenv_t*);
_ACRTIMP int __cdecl fegetround(void);
_ACRTIMP int __cdecl fesetround(int); _ACRTIMP int __cdecl fesetround(int);
#ifdef __cplusplus #ifdef __cplusplus
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment