diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index afff1afb6..12091359d 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -4270,23 +4270,15 @@ void OpDispatchBuilder::CMPXCHGPairOp(OpcodeArgs) { SetRFLAG(ZFResult); CalculateDeferredFlags(); - auto CondJump_ = CondJump(ZFResult); + auto UpdateIfNotZF = [this](auto Reg, auto Value) { + // Always use 64-bit csel to preserve existing upper bits. If we have a + // 32-bit cmpxchg in a 64-bit context, Value will be zeroed in upper bits. + StoreGPRRegister(Reg, _NZCVSelect(OpSize::i64Bit, CondClassType{COND_NEQ}, + Value, LoadGPRRegister(Reg))); + }; - // Make sure to start a new block after ending this one - auto JumpTarget = CreateNewCodeBlockAfter(GetCurrentBlock()); - SetFalseJumpTarget(CondJump_, JumpTarget); - SetCurrentCodeBlock(JumpTarget); - StartNewBlock(); - - StoreGPRRegister(X86State::REG_RAX, Result_Lower); - StoreGPRRegister(X86State::REG_RDX, Result_Upper); - - auto Jump_ = Jump(); - auto NextJumpTarget = CreateNewCodeBlockAfter(JumpTarget); - SetJumpTarget(Jump_, NextJumpTarget); - SetTrueJumpTarget(CondJump_, NextJumpTarget); - SetCurrentCodeBlock(NextJumpTarget); - StartNewBlock(); + UpdateIfNotZF(X86State::REG_RAX, Result_Lower); + UpdateIfNotZF(X86State::REG_RDX, Result_Upper); } void OpDispatchBuilder::CreateJumpBlocks(fextl::vector const *Blocks) {