Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #426 from shuffle2/xsave-workaround-fix
Redo commit 932945d
Fixes crashes from running on hardware with FMA3 support and software which doesn't support it.
  • Loading branch information
shuffle2 committed May 27, 2014
2 parents f5e1dee + 58bcc3d commit 3d21c67
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 26 deletions.
51 changes: 25 additions & 26 deletions Source/Core/Common/XSaveWorkaround.cpp
Expand Up @@ -2,39 +2,38 @@
// Licensed under GPLv2
// Refer to the license.txt file included.

#if defined(_WIN32) && defined(_ARCH_64)
#if defined(_WIN32) && defined(_M_X86_64)

#include <math.h>
#include <Windows.h>

// This puts the rest of this translation unit into a segment which is
// initialized by the CRT *before* any of the other code (including C++
// static initializers).
#pragma warning(disable : 4075)
#pragma init_seg(".CRT$XCB")

struct EnableXSaveWorkaround
void EnableXSaveWorkaround()
{
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))
{
// 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);
}
_set_FMA3_enable(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;
};

static EnableXSaveWorkaround enableXSaveWorkaround;

// N.B. Any code after this will still be in the .CRT$XCB segment. Please just
// do not append any code here unless it is intended to be executed before
// static initializers.

#endif
5 changes: 5 additions & 0 deletions Source/VSProps/Base.props
Expand Up @@ -106,6 +106,11 @@
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
</Link>
<!--Link Base:Application-->
<Link Condition="'$(ConfigurationType)'=='Application'">
<!--See Common/EnableXSaveWorkaround.cpp-->
<ForceSymbolReferences>XSaveWorkaround</ForceSymbolReferences>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
<LinkTimeCodeGeneration Condition="'$(DolphinRelease)'=='true'">true</LinkTimeCodeGeneration>
Expand Down

2 comments on commit 3d21c67

@CarlKenner
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have no idea how much pain, suffering, and lost productivity this commit caused me today. :-)
It took me forever to work out why my branch was now failing before any code had even been run. I had assumed it was my fault. Then I looked through the other commits I had pulled and finally found where someone had inserted some code that ran before any code had even been run. :-)

@shuffle2
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I, also, feel the pain of supporting dumb users.

Please sign in to comment.