mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 19:00:17 +02:00
Merge pull request #3429 from alyssarosenzweig/cleanup/nzcv-helpers
Cleanup NZCV metadata
This commit is contained in:
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
|
||||
|
||||
Reference in new issue
Block a user