MCPcopy Create free account
hub / github.com/FEX-Emu/FEX / CMPXCHGPairOp

Method CMPXCHGPairOp

FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp:3858–3903  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

3856}
3857
3858void OpDispatchBuilder::CMPXCHGPairOp(OpcodeArgs) {
3859 // Calculate flags early.
3860 CalculateDeferredFlags();
3861
3862 // REX.W used to determine if it is 16byte or 8byte
3863 // Unlike CMPXCHG, the destination can only be a memory location
3864 const auto Size = Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_REX_WIDENING ? OpSize::i64Bit : OpSize::i32Bit;
3865
3866 HandledLock = (Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_LOCK) != 0;
3867
3868 // If this is a memory location then we want the pointer to it
3869 Ref Src1 = MakeSegmentAddress(Op, Op->Dest);
3870
3871 // Load the full 64-bit registers, all the users ignore the upper 32-bits for
3872 // 32-bit only cmpxchg. This saves some zero extension.
3873 Ref Expected_Lower = LoadGPRRegister(X86State::REG_RAX);
3874 Ref Expected_Upper = LoadGPRRegister(X86State::REG_RDX);
3875 Ref Desired_Lower = LoadGPRRegister(X86State::REG_RBX);
3876 Ref Desired_Upper = LoadGPRRegister(X86State::REG_RCX);
3877
3878 // ssa0 = Expected
3879 // ssa1 = Desired
3880 // ssa2 = MemoryLocation
3881
3882 // DataSrc = *MemSrc
3883 // if (DataSrc == Expected) { *MemSrc == Desired; } Expected = DataSrc
3884 // This will write to memory! Careful!
3885 // Third operand must be a calculated guest memory address
3886
3887 Ref Result_Lower = _AllocateGPR(true);
3888 Ref Result_Upper = _AllocateGPRAfter(Result_Lower);
3889 _CASPair(Size, Expected_Lower, Expected_Upper, Desired_Lower, Desired_Upper, Src1, Result_Lower, Result_Upper);
3890
3891 HandleNZCV_RMW();
3892 _CmpPairZ(Size, Result_Lower, Result_Upper, Expected_Lower, Expected_Upper);
3893 CalculateDeferredFlags();
3894
3895 auto UpdateIfNotZF = [this](auto Reg, auto Value) {
3896 // Always use 64-bit csel to preserve existing upper bits. If we have a
3897 // 32-bit cmpxchg in a 64-bit context, Value will be zeroed in upper bits.
3898 StoreGPRRegister(Reg, NZCVSelect(OpSize::i64Bit, {COND_NEQ}, Value, LoadGPRRegister(Reg)));
3899 };
3900
3901 UpdateIfNotZF(X86State::REG_RAX, Result_Lower);
3902 UpdateIfNotZF(X86State::REG_RDX, Result_Upper);
3903}
3904
3905void OpDispatchBuilder::CreateJumpBlocks(const fextl::vector<FEXCore::Frontend::Decoder::DecodedBlocks>* Blocks) {
3906 Ref PrevCodeBlock {};

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected