diff --git a/src/backends/generic/misc.c b/src/backends/generic/misc.c index c9a4b5fb..c5e280cb 100644 --- a/src/backends/generic/misc.c +++ b/src/backends/generic/misc.c @@ -154,3 +154,26 @@ const char *Sys_GetBinaryDir(void) return exeDir; } + +#if defined (__GNUC__) && (__i386 || __x86_64__) +void Sys_SetupFPU(void) { + // Get current x87 control word + volatile unsigned short old_cw = 0; + asm ("fstcw %0" : : "m" (*&old_cw)); + unsigned short new_cw = old_cw; + + // The precision is set through bit 8 and 9. For + // double precision bit 8 must unset and bit 9 set. + new_cw &= ~(1 << 8); + new_cw |= (1 << 9); + + // Setting the control word is expensive since it + // resets the FPU state. Do it only if necessary. + if (new_cw != old_cw) { + asm ("fldcw %0" : : "m" (*&new_cw)); + } +} +#else +void Sys_SetupFPU(void) { +} +#endif diff --git a/src/backends/unix/main.c b/src/backends/unix/main.c index 0ff80d2d..ca5e1455 100644 --- a/src/backends/unix/main.c +++ b/src/backends/unix/main.c @@ -52,6 +52,9 @@ main(int argc, char **argv) /* register signal handler */ registerHandler(); + /* Setup FPU if necessary */ + Sys_SetupFPU(); + /* Are we portable? */ for (i = 0; i < argc; i++) { if (strcmp(argv[i], "-portable") == 0) { diff --git a/src/backends/windows/system.c b/src/backends/windows/system.c index 4a758174..94c42673 100644 --- a/src/backends/windows/system.c +++ b/src/backends/windows/system.c @@ -785,6 +785,9 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, /* Make the current instance global */ global_hInstance = hInstance; + /* Setup FPU if necessary */ + Sys_SetupFPU(); + /* Force DPI awareness */ Sys_SetHighDPIMode(); diff --git a/src/common/header/common.h b/src/common/header/common.h index 95aa87f8..c192f3d3 100644 --- a/src/common/header/common.h +++ b/src/common/header/common.h @@ -773,6 +773,7 @@ void Sys_FreeLibrary(void *handle); void *Sys_LoadLibrary(const char *path, const char *sym, void **handle); void *Sys_GetProcAddress(void *handle, const char *sym); void Sys_RedirectStdout(void); +void Sys_SetupFPU(void); /* CLIENT / SERVER SYSTEMS */