Skip to content

Commit

Permalink
OpcodeDispatcher: optimize gpr cmpxchg
Browse files Browse the repository at this point in the history
NZCV stuff.

Signed-off-by: Alyssa Rosenzweig <[email protected]>
  • Loading branch information
alyssarosenzweig committed Jan 12, 2024
1 parent 0a6e875 commit e8945df
Showing 1 changed file with 19 additions and 24 deletions.
43 changes: 19 additions & 24 deletions FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

// 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);
// Compare RAX with the destination, setting flags accordingly.
OrderedNode *Result = _Sub(IR::SizeToOpSize(GPRSize), Src3Lower, Src1Lower);
GenerateFlags_SUB(Op, Result, Src3Lower, Src1Lower);
CalculateDeferredFlags();

// 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,
Src3, Src1Lower);
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;
Expand Down

0 comments on commit e8945df

Please sign in to comment.