IR: Switch to dedicated NZCV load/store

Semantics differ markedly from the non-NZCV flags, splitting this out makes it a
lot easier to do things correctly imho. Gets the dest/src size correct
(important for spilling), as well as makes our existing opt passes skip this
which is needed for correctness at the moment anyway.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
This commit is contained in:
Alyssa Rosenzweig 2023-11-08 08:51:17 -04:00
parent cf6b21564c
commit b3055523b4
4 changed files with 28 additions and 11 deletions

View File

@ -1031,23 +1031,29 @@ DEF_OP(FillRegister) {
}
}
DEF_OP(LoadNZCV) {
auto Dst = GetReg(Node);
ldr(Dst.W(), STATE, offsetof(FEXCore::Core::CPUState, flags[0]) + 24);
}
DEF_OP(StoreNZCV) {
auto Op = IROp->C<IR::IROp_StoreNZCV>();
str(GetReg(Op->Value.ID()).W(), STATE, offsetof(FEXCore::Core::CPUState, flags[0]) + 24);
}
DEF_OP(LoadFlag) {
auto Op = IROp->C<IR::IROp_LoadFlag>();
auto Dst = GetReg(Node);
if (Op->Flag == 24 /* NZCV */)
ldr(Dst.W(), STATE, offsetof(FEXCore::Core::CPUState, flags[0]) + Op->Flag);
else
ldrb(Dst, STATE, offsetof(FEXCore::Core::CPUState, flags[0]) + Op->Flag);
ldrb(Dst, STATE, offsetof(FEXCore::Core::CPUState, flags[0]) + Op->Flag);
}
DEF_OP(StoreFlag) {
auto Op = IROp->C<IR::IROp_StoreFlag>();
if (Op->Flag == 24 /* NZCV */)
str(GetReg(Op->Value.ID()).W(), STATE, offsetof(FEXCore::Core::CPUState, flags[0]) + Op->Flag);
else
strb(GetReg(Op->Value.ID()), STATE, offsetof(FEXCore::Core::CPUState, flags[0]) + Op->Flag);
strb(GetReg(Op->Value.ID()), STATE, offsetof(FEXCore::Core::CPUState, flags[0]) + Op->Flag);
}
FEXCore::ARMEmitter::ExtendedMemOperand Arm64JITCore::GenerateMemOperand(uint8_t AccessSize,

View File

@ -1243,7 +1243,7 @@ private:
OrderedNode *GetNZCV() {
if (!CachedNZCV) {
CachedNZCV = _LoadFlag(FEXCore::X86State::RFLAG_NZCV_LOC);
CachedNZCV = _LoadNZCV();
// We don't know what's set
PossiblySetNZCVBits = ~0;

View File

@ -313,7 +313,7 @@ void OpDispatchBuilder::CalculateDeferredFlags(uint32_t FlagsToCalculateMask) {
if (CurrentDeferredFlags.Type == FlagsGenerationType::TYPE_NONE) {
// Nothing to do
if (NZCVDirty && CachedNZCV)
_StoreFlag(CachedNZCV, FEXCore::X86State::RFLAG_NZCV_LOC);
_StoreNZCV(CachedNZCV);
CachedNZCV = nullptr;
NZCVDirty = false;
@ -501,7 +501,7 @@ void OpDispatchBuilder::CalculateDeferredFlags(uint32_t FlagsToCalculateMask) {
CurrentDeferredFlags.Type = FlagsGenerationType::TYPE_NONE;
if (NZCVDirty && CachedNZCV)
_StoreFlag(CachedNZCV, FEXCore::X86State::RFLAG_NZCV_LOC);
_StoreNZCV(CachedNZCV);
CachedNZCV = nullptr;
NZCVDirty = false;

View File

@ -447,6 +447,17 @@
]
},
"GPR = LoadNZCV": {
"Desc": ["Loads value of NZCV register"],
"DestSize": "4"
},
"StoreNZCV GPR:$Value": {
"HasSideEffects": true,
"Desc": ["Stores value to NZCV register"],
"DestSize": "4"
},
"GPR = LoadFlag u32:$Flag": {
"Desc": ["Loads an x86-64 flag from the context object",
"Specialized to allow flexible implementation of flag handling"