Manually save and restore the FPU rounding mode on Windows
Apparently there is a bug with at least MinGW-W64 where fegetenv and fesetenv do not properly save and restore the FPU rounding mode, resulting in the rounding mode remaining as round-to-zero after certain function calls. I do not know if this also affects MSVC, but better safe than sorry for now.
This commit is contained in:
@@ -295,6 +295,13 @@ void SetMixerFPUMode(FPUCtl *ctl)
|
||||
{
|
||||
#ifdef HAVE_FENV_H
|
||||
fegetenv(STATIC_CAST(fenv_t, ctl));
|
||||
#ifdef _WIN32
|
||||
/* HACK: A nasty bug in MinGW-W64 causes fegetenv and fesetenv to not save
|
||||
* and restore the FPU rounding mode, so we have to do it manually. Don't
|
||||
* know if this also applies to MSVC.
|
||||
*/
|
||||
ctl->round_mode = fegetround();
|
||||
#endif
|
||||
#if defined(__GNUC__) && defined(HAVE_SSE)
|
||||
/* FIXME: Some fegetenv implementations can get the SSE environment too?
|
||||
* How to tell when it does? */
|
||||
@@ -341,6 +348,9 @@ void RestoreFPUMode(const FPUCtl *ctl)
|
||||
{
|
||||
#ifdef HAVE_FENV_H
|
||||
fesetenv(STATIC_CAST(fenv_t, ctl));
|
||||
#ifdef _WIN32
|
||||
fesetround(ctl->round_mode);
|
||||
#endif
|
||||
#if defined(__GNUC__) && defined(HAVE_SSE)
|
||||
if((CPUCapFlags&CPU_CAP_SSE))
|
||||
__asm__ __volatile__("ldmxcsr %0" : : "m" (*&ctl->sse_state));
|
||||
|
||||
@@ -898,6 +898,9 @@ void ALCcontext_ProcessUpdates(ALCcontext *context);
|
||||
typedef struct {
|
||||
#ifdef HAVE_FENV_H
|
||||
DERIVE_FROM_TYPE(fenv_t);
|
||||
#ifdef _WIN32
|
||||
int round_mode;
|
||||
#endif
|
||||
#else
|
||||
int state;
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user