OpcodeDispatcher: optimize gpr cmpxchg

NZCV stuff.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
This commit is contained in:
Alyssa Rosenzweig 2024-01-12 11:31:36 -04:00
parent 0a6e875329
commit e8945dfb6d

View File

@ -4288,40 +4288,35 @@ void OpDispatchBuilder::CMPXCHGOp(OpcodeArgs) {
Src3Lower = Src3;
}
// If our destination is a GPR then this behaves differently
// RAX = RAX == Op1 ? RAX : Op1
// AKA if they match then don't touch RAX value
// Otherwise set it to the rm operand
OrderedNode *CASResult = _Select(FEXCore::IR::COND_EQ,
Src1Lower, Src3Lower,
Src3Lower, Src1Lower);
// Compare RAX with the destination, setting flags accordingly.
OrderedNode *Result = _Sub(IR::SizeToOpSize(GPRSize), Src3Lower, Src1Lower);
GenerateFlags_SUB(Op, Result, Src3Lower, Src1Lower);
CalculateDeferredFlags();
// Op1 = RAX == Op1 ? Op2 : Op1
// If they match then set the rm operand to the input
// else don't set the rm operand
OrderedNode *DestResult = _Select(FEXCore::IR::COND_EQ,
Src1Lower, Src3Lower,
Src2, Src1);
// Store in to GPR Dest
// Have to make sure this is after the result store in RAX for when Dest == RAX
if (GPRSize == 8 && Size == 4) {
// This allows us to only hit the ZEXT case on failure
OrderedNode *RAXResult = _Select(FEXCore::IR::COND_EQ,
CASResult, Src3Lower,
OrderedNode *RAXResult = _NZCVSelect(IR::i64Bit, CondClassType{COND_EQ},
Src3, Src1Lower);
// When the size is 4 we need to make sure not zext the GPR when the comparison fails
StoreGPRRegister(X86State::REG_RAX, RAXResult);
StoreResult_WithOpSize(GPRClass, Op, Op->Dest, DestResult, GPRSize, -1);
}
else {
StoreGPRRegister(X86State::REG_RAX, CASResult, Size);
StoreResult(GPRClass, Op, DestResult, -1);
StoreGPRRegister(X86State::REG_RAX, Src1Lower, Size);
}
OrderedNode *Result = _Sub(IR::SizeToOpSize(GPRSize), Src3Lower, CASResult);
GenerateFlags_SUB(Op, Result, Src3Lower, CASResult);
// Op1 = RAX == Op1 ? Op2 : Op1
// If they match then set the rm operand to the input
// else don't set the rm operand
OrderedNode *DestResult = _NZCVSelect(IR::i64Bit, CondClassType{COND_EQ},
Src2, Src1);
// Store in to GPR Dest
if (GPRSize == 8 && Size == 4) {
StoreResult_WithOpSize(GPRClass, Op, Op->Dest, DestResult, GPRSize, -1);
} else {
StoreResult(GPRClass, Op, DestResult, -1);
}
}
else {
HandledLock = Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_LOCK;