Merge pull request #3429 from alyssarosenzweig/cleanup/nzcv-helpers

Cleanup NZCV metadata
This commit is contained in:
Alyssa Rosenzweig authored and GitHub committed 2024-02-20 10:18:15 -04:00
commit 9c38332e7e
4 files changed
+37 -53

No files matched your search

@@ -441,14 +441,7 @@ void OpDispatchBuilder::SecondaryALUOp(OpcodeArgs) {
break;
}
case FEXCore::IR::IROps::OP_ANDWITHFLAGS: {
InvalidateDeferredFlags();
// SF/ZF/CF/OF
CachedNZCV = nullptr;
PossiblySetNZCVBits = (1u << 31) | (1u << 30);
NZCVDirty = false;
// PF/AF
HandleNZ00Write();
CalculatePF(Result);
_InvalidateFlags(1 << X86State::RFLAG_AF_RAW_LOC);
break;
@@ -1298,16 +1291,8 @@ void OpDispatchBuilder::TESTOp(OpcodeArgs) {
Src = Dest;
}
InvalidateDeferredFlags();
// SF/ZF/CF/OF
OrderedNode *ALUOp = _AndWithFlags(IR::SizeToOpSize(Size), Dest, Src);
CachedNZCV = nullptr;
PossiblySetNZCVBits = (1u << 31) | (1u << 30);
NZCVDirty = false;
// PF/AF
CalculatePF(ALUOp);
HandleNZ00Write();
CalculatePF(_AndWithFlags(IR::SizeToOpSize(Size), Dest, Src));
_InvalidateFlags(1 << X86State::RFLAG_AF_RAW_LOC);
}
@@ -5278,14 +5263,7 @@ void OpDispatchBuilder::ALUOpImpl(OpcodeArgs, FEXCore::IR::IROps ALUIROp, FEXCor
break;
}
case FEXCore::IR::IROps::OP_ANDWITHFLAGS: {
InvalidateDeferredFlags();
// SF/ZF/CF/OF
CachedNZCV = nullptr;
PossiblySetNZCVBits = (1u << 31) | (1u << 30);
NZCVDirty = false;
// PF/AF
HandleNZ00Write();
CalculatePF(Result);
_InvalidateFlags(1 << X86State::RFLAG_AF_RAW_LOC);
break;
@@ -1263,6 +1263,30 @@ private:
return NZCVMask;
}
// Set flag tracking to prepare for an operation that directly writes NZCV. If
// some bits are known to be zeroed, the PossiblySetNZCVBits mask can be
// passed. Otherwise, it defaults to assuming all bits may be set after
// (this is conservative).
void HandleNZCVWrite(uint32_t _PossiblySetNZCVBits = ~0) {
InvalidateDeferredFlags();
CachedNZCV = nullptr;
PossiblySetNZCVBits = _PossiblySetNZCVBits;
NZCVDirty = false;
}
// Set flag tracking to prepare for a read-modify-write operation on NZCV.
void HandleNZCV_RMW(uint32_t _PossiblySetNZCVBits = ~0) {
if (NZCVDirty && CachedNZCV)
_StoreNZCV(CachedNZCV);
HandleNZCVWrite(_PossiblySetNZCVBits);
}
// Special case of the above where we are known to zero C/V
void HandleNZ00Write() {
HandleNZCVWrite((1u << 31) | (1u << 30));
}
OrderedNode *GetNZCV() {
if (!CachedNZCV) {
CachedNZCV = _LoadNZCV();
@@ -495,12 +495,8 @@ void OpDispatchBuilder::CalculateFlags_ADC(uint8_t SrcSize, OrderedNode *Res, Or
CalculatePF(Res);
if (SrcSize >= 4) {
if (NZCVDirty && CachedNZCV)
_StoreNZCV(CachedNZCV);
CachedNZCV = nullptr;
HandleNZCV_RMW();
_AdcNZCV(OpSize, Src1, Src2);
PossiblySetNZCVBits = ~0;
} else {
// SF/ZF
SetNZ_ZeroCV(SrcSize, Res);
@@ -531,13 +527,8 @@ void OpDispatchBuilder::CalculateFlags_SBB(uint8_t SrcSize, OrderedNode *Res, Or
// Rectify input carry
CarryInvert();
if (NZCVDirty && CachedNZCV)
_StoreNZCV(CachedNZCV);
CachedNZCV = nullptr;
NZCVDirty = false;
HandleNZCV_RMW();
_SbbNZCV(OpSize, Src1, Src2);
PossiblySetNZCVBits = ~0;
// Rectify output carry
CarryInvert();
@@ -568,10 +559,8 @@ void OpDispatchBuilder::CalculateFlags_SUB(uint8_t SrcSize, OrderedNode *Res, Or
// Stash CF before stomping over it
auto OldCF = UpdateCF ? nullptr : GetRFLAG(FEXCore::X86State::RFLAG_CF_RAW_LOC);
HandleNZCVWrite();
_SubNZCV(IR::SizeToOpSize(SrcSize), Src1, Src2);
CachedNZCV = nullptr;
NZCVDirty = false;
PossiblySetNZCVBits = ~0;
// If we're updating CF, we need to invert it for correctness. If we're not
// updating CF, we need to restore the CF since we stomped over it.
@@ -590,10 +579,8 @@ void OpDispatchBuilder::CalculateFlags_ADD(uint8_t SrcSize, OrderedNode *Res, Or
// Stash CF before stomping over it
auto OldCF = UpdateCF ? nullptr : GetRFLAG(FEXCore::X86State::RFLAG_CF_RAW_LOC);
HandleNZCVWrite();
_AddNZCV(IR::SizeToOpSize(SrcSize), Src1, Src2);
CachedNZCV = nullptr;
NZCVDirty = false;
PossiblySetNZCVBits = ~0;
// We stomped over CF while calculation flags, restore it.
if (!UpdateCF)
@@ -601,6 +588,8 @@ void OpDispatchBuilder::CalculateFlags_ADD(uint8_t SrcSize, OrderedNode *Res, Or
}
void OpDispatchBuilder::CalculateFlags_MUL(uint8_t SrcSize, OrderedNode *Res, OrderedNode *High) {
HandleNZCVWrite();
// PF/AF/ZF/SF
// Undefined
{
@@ -619,13 +608,12 @@ void OpDispatchBuilder::CalculateFlags_MUL(uint8_t SrcSize, OrderedNode *Res, Or
// undefined, this does what we need.
auto Zero = _Constant(0);
_CondAddNZCV(OpSize::i64Bit, Zero, Zero, CondClassType{COND_EQ}, 0x3 /* nzCV */);
CachedNZCV = nullptr;
NZCVDirty = false;
PossiblySetNZCVBits = ~0;
}
}
void OpDispatchBuilder::CalculateFlags_UMUL(OrderedNode *High) {
HandleNZCVWrite();
auto Zero = _Constant(0);
OpSize Size = IR::SizeToOpSize(GetOpSize(High));
@@ -645,9 +633,6 @@ void OpDispatchBuilder::CalculateFlags_UMUL(OrderedNode *High) {
// If High = 0, then sets to nZcv. Else sets to nzCV. Since SF/ZF undefined,
// this does what we need.
_CondAddNZCV(Size, Zero, Zero, CondClassType{COND_EQ}, 0x3 /* nzCV */);
CachedNZCV = nullptr;
NZCVDirty = false;
PossiblySetNZCVBits = ~0;
}
}
@@ -3422,15 +3422,12 @@ void OpDispatchBuilder::VPALIGNROp(OpcodeArgs) {
template<size_t ElementSize>
void OpDispatchBuilder::UCOMISxOp(OpcodeArgs) {
InvalidateDeferredFlags();
const auto SrcSize = Op->Src[0].IsGPR() ? GetGuestVectorLength() : GetSrcSize(Op);
OrderedNode *Src1 = LoadSource_WithOpSize(FPRClass, Op, Op->Dest, GetGuestVectorLength(), Op->Flags);
OrderedNode *Src2 = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], SrcSize, Op->Flags);
CachedNZCV = nullptr;
HandleNZCVWrite();
_FCmp(ElementSize, Src1, Src2);
PossiblySetNZCVBits = ~0;
ConvertNZCVToSSE();
// Zero AF. Note that the comparison sets the raw PF to 0/1 above, so PF[4] is