diff --git a/Data/AppConfig/VC_redist.x64.exe.json b/Data/AppConfig/VC_redist.x64.exe.json new file mode 100644 index 000000000..95f5d5ee6 --- /dev/null +++ b/Data/AppConfig/VC_redist.x64.exe.json @@ -0,0 +1,5 @@ +{ + "Config": { + "x86dec_SynchronizeRIPOnAllBlocks": "1" + } +} diff --git a/Data/AppConfig/VC_redist.x86.exe.json b/Data/AppConfig/VC_redist.x86.exe.json new file mode 100644 index 000000000..95f5d5ee6 --- /dev/null +++ b/Data/AppConfig/VC_redist.x86.exe.json @@ -0,0 +1,5 @@ +{ + "Config": { + "x86dec_SynchronizeRIPOnAllBlocks": "1" + } +} diff --git a/Data/AppConfig/vcredist_x64.exe.json b/Data/AppConfig/vcredist_x64.exe.json new file mode 100644 index 000000000..95f5d5ee6 --- /dev/null +++ b/Data/AppConfig/vcredist_x64.exe.json @@ -0,0 +1,5 @@ +{ + "Config": { + "x86dec_SynchronizeRIPOnAllBlocks": "1" + } +} diff --git a/Data/AppConfig/vcredist_x86.exe.json b/Data/AppConfig/vcredist_x86.exe.json new file mode 100644 index 000000000..95f5d5ee6 --- /dev/null +++ b/Data/AppConfig/vcredist_x86.exe.json @@ -0,0 +1,5 @@ +{ + "Config": { + "x86dec_SynchronizeRIPOnAllBlocks": "1" + } +} diff --git a/External/FEXCore/Source/Interface/Config/Config.json.in b/External/FEXCore/Source/Interface/Config/Config.json.in index 466938439..9ebbaf42b 100644 --- a/External/FEXCore/Source/Interface/Config/Config.json.in +++ b/External/FEXCore/Source/Interface/Config/Config.json.in @@ -309,6 +309,16 @@ "Forces a process to stall out on initialization", "Useful for a process that keeps restarting and doesn't work" ] + }, + "x86dec_SynchronizeRIPOnAllBlocks": { + "Type": "bool", + "Default": "false", + "Desc": [ + "An application that uses try-catch or longjump extensively needs the ability to do context aware state flushing", + "In the case of FEX's block-linking, it won't always ensure that RIP is synchronized.", + "If an exception occurs and RIP isn't synchronized, then FEX's exception stack restore may not long jump as expected", + "Can be useful for Wine applications that rely on stack unwinding" + ] } }, "Misc": { diff --git a/External/FEXCore/Source/Interface/Context/Context.h b/External/FEXCore/Source/Interface/Context/Context.h index 766ae0953..e2027e397 100644 --- a/External/FEXCore/Source/Interface/Context/Context.h +++ b/External/FEXCore/Source/Interface/Context/Context.h @@ -113,6 +113,7 @@ namespace FEXCore::Context { FEX_CONFIG_OPT(ParanoidTSO, PARANOIDTSO); FEX_CONFIG_OPT(CacheObjectCodeCompilation, CACHEOBJECTCODECOMPILATION); FEX_CONFIG_OPT(x87ReducedPrecision, X87REDUCEDPRECISION); + FEX_CONFIG_OPT(x86dec_SynchronizeRIPOnAllBlocks, X86DEC_SYNCHRONIZERIPONALLBLOCKS); } Config; FEXCore::HostFeatures HostFeatures; diff --git a/External/FEXCore/Source/Interface/Core/Core.cpp b/External/FEXCore/Source/Interface/Core/Core.cpp index 73a5fff76..405407761 100644 --- a/External/FEXCore/Source/Interface/Core/Core.cpp +++ b/External/FEXCore/Source/Interface/Core/Core.cpp @@ -762,6 +762,13 @@ namespace FEXCore::Context { // Reset any block-specific state Thread->OpDispatcher->StartNewBlock(); + if (Config.x86dec_SynchronizeRIPOnAllBlocks) { + // Ensure the RIP is synchronized to the context on block entry. + // In the case of block linking, the RIP may not have synchronized. + auto NewRIP = Thread->OpDispatcher->_EntrypointOffset(Block.Entry - GuestRIP, GPRSize); + Thread->OpDispatcher->_StoreContext(GPRSize, IR::GPRClass, NewRIP, offsetof(FEXCore::Core::CPUState, rip)); + } + uint64_t InstsInBlock = Block.NumInstructions; for (size_t i = 0; i < InstsInBlock; ++i) { @@ -775,7 +782,7 @@ namespace FEXCore::Context { if (ExtendedDebugInfo) { Thread->OpDispatcher->_GuestOpcode(Block.Entry + BlockInstructionsLength - GuestRIP); } - + if (Config.SMCChecks == FEXCore::Config::CONFIG_SMC_FULL) { auto ExistingCodePtr = reinterpret_cast(Block.Entry + BlockInstructionsLength); @@ -1292,4 +1299,4 @@ namespace FEXCore::Context { Thread->FrontendDecoder->SetExternalBranches(ExternalBranches); Thread->FrontendDecoder->SetSectionMaxAddress(SectionMaxAddress); } -} \ No newline at end of file +}