summaryrefslogtreecommitdiff
path: root/Source/Core/Common/XSaveWorkaround.cpp
diff options
context:
space:
mode:
authorJules Blok <jules.blok@gmail.com>2015-06-10 00:00:12 +0200
committerJules Blok <jules.blok@gmail.com>2015-06-10 00:00:12 +0200
commit7dfced21a2e5aac7195e0e1ad76468e30306766b (patch)
treebd671b639d3d911460b767caabad8fc8a759a6bf /Source/Core/Common/XSaveWorkaround.cpp
parentc25be031fc1031d795157d8344b87b7841145197 (diff)
parent7b0a65e295c784f9d573f2ef52d4e2a7b9bb2889 (diff)
Merge branch 'master' into stable
Diffstat (limited to 'Source/Core/Common/XSaveWorkaround.cpp')
-rw-r--r--Source/Core/Common/XSaveWorkaround.cpp61
1 files changed, 61 insertions, 0 deletions
diff --git a/Source/Core/Common/XSaveWorkaround.cpp b/Source/Core/Common/XSaveWorkaround.cpp
new file mode 100644
index 0000000000..a91af47a39
--- /dev/null
+++ b/Source/Core/Common/XSaveWorkaround.cpp
@@ -0,0 +1,61 @@
+// Copyright 2014 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#if defined(_WIN32)
+
+#include <math.h>
+#include <Windows.h>
+
+typedef decltype(&GetEnabledXStateFeatures) GetEnabledXStateFeatures_t;
+
+int __cdecl EnableXSaveWorkaround()
+{
+ // Some Windows environments may have hardware support for AVX/FMA,
+ // but the OS does not support it. The CRT math library does not support
+ // this scenario, so we have to manually tell it not to use FMA3
+ // instructions.
+
+ // The API name is somewhat misleading - we're testing for OS support
+ // here.
+ if (!IsProcessorFeaturePresent(PF_XSAVE_ENABLED))
+ {
+ _set_FMA3_enable(0);
+ return 0;
+ }
+
+ // Even if XSAVE feature is enabled, we have to see if
+ // GetEnabledXStateFeatures function is present, and see what it says about
+ // AVX state.
+ auto kernel32Handle = GetModuleHandle(TEXT("kernel32.dll"));
+ if (kernel32Handle == nullptr)
+ {
+ std::abort();
+ }
+
+ auto pGetEnabledXStateFeatures = (GetEnabledXStateFeatures_t)GetProcAddress(
+ kernel32Handle, "GetEnabledXStateFeatures");
+ if (pGetEnabledXStateFeatures == nullptr ||
+ (pGetEnabledXStateFeatures() & XSTATE_MASK_AVX) == 0)
+ {
+ _set_FMA3_enable(0);
+ }
+
+ return 0;
+}
+
+// Create a segment which is recognized by the linker to be part of the CRT
+// initialization. XI* = C startup, XC* = C++ startup. "A" placement is reserved
+// for system use. Thus, the earliest we can get is XIB (C startup is before
+// C++).
+#pragma section(".CRT$XIB", read)
+
+// Place a symbol in the special segment, make it have C linkage so that
+// referencing it doesn't require ugly decorated names.
+// Use /include:XSaveWorkaround linker flag to enable this.
+extern "C" {
+ __declspec(allocate(".CRT$XIB"))
+ decltype(&EnableXSaveWorkaround) XSaveWorkaround = EnableXSaveWorkaround;
+};
+
+#endif