diff --git a/External/FEXCore/Source/Interface/Core/Interpreter/MemoryOps.cpp b/External/FEXCore/Source/Interface/Core/Interpreter/MemoryOps.cpp index 096da6f6a..d4c355b97 100644 --- a/External/FEXCore/Source/Interface/Core/Interpreter/MemoryOps.cpp +++ b/External/FEXCore/Source/Interface/Core/Interpreter/MemoryOps.cpp @@ -190,19 +190,31 @@ DEF_OP(LoadFlag) { uintptr_t ContextPtr = reinterpret_cast(Data->State->CurrentFrame); ContextPtr += offsetof(FEXCore::Core::CPUState, flags[0]); ContextPtr += Op->Flag; - uint8_t const *MemData = reinterpret_cast(ContextPtr); - GD = *MemData; + + if (Op->Flag == 24 /* NZCV */) { + uint32_t const *MemData = reinterpret_cast(ContextPtr); + GD = *MemData; + } else { + uint8_t const *MemData = reinterpret_cast(ContextPtr); + GD = *MemData; + } } DEF_OP(StoreFlag) { auto Op = IROp->C(); - uint8_t Arg = *GetSrc(Data->SSAData, Op->Value); + uint32_t Arg = *GetSrc(Data->SSAData, Op->Value); uintptr_t ContextPtr = reinterpret_cast(Data->State->CurrentFrame); ContextPtr += offsetof(FEXCore::Core::CPUState, flags[0]); ContextPtr += Op->Flag; - uint8_t *MemData = reinterpret_cast(ContextPtr); - *MemData = Arg; + + if (Op->Flag == 24 /* NZCV */) { + uint32_t *MemData = reinterpret_cast(ContextPtr); + *MemData = Arg; + } else { + uint8_t *MemData = reinterpret_cast(ContextPtr); + *MemData = Arg; + } } DEF_OP(LoadMem) { diff --git a/External/FEXCore/Source/Interface/Core/JIT/Arm64/MemoryOps.cpp b/External/FEXCore/Source/Interface/Core/JIT/Arm64/MemoryOps.cpp index 8805637f6..33aedd381 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/Arm64/MemoryOps.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/Arm64/MemoryOps.cpp @@ -1051,12 +1051,20 @@ DEF_OP(FillRegister) { DEF_OP(LoadFlag) { auto Op = IROp->C(); auto Dst = GetReg(Node); - ldrb(Dst, STATE, offsetof(FEXCore::Core::CPUState, flags[0]) + Op->Flag); + + 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); } DEF_OP(StoreFlag) { auto Op = IROp->C(); - strb(GetReg(Op->Value.ID()), STATE, offsetof(FEXCore::Core::CPUState, flags[0]) + Op->Flag); + + 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); } FEXCore::ARMEmitter::ExtendedMemOperand Arm64JITCore::GenerateMemOperand(uint8_t AccessSize, diff --git a/External/FEXCore/Source/Interface/Core/JIT/x86_64/MemoryOps.cpp b/External/FEXCore/Source/Interface/Core/JIT/x86_64/MemoryOps.cpp index 98a7f3807..775d4d27c 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/x86_64/MemoryOps.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/x86_64/MemoryOps.cpp @@ -601,14 +601,22 @@ DEF_OP(LoadFlag) { auto Op = IROp->C(); auto Dst = GetDst(Node); - movzx(Dst, byte [STATE + (offsetof(FEXCore::Core::CPUState, flags[0]) + Op->Flag)]); + + if (Op->Flag == 24 /* NZCV */) + mov(Dst.cvt32(), dword [STATE + (offsetof(FEXCore::Core::CPUState, flags[0]) + Op->Flag)]); + else + movzx(Dst, byte [STATE + (offsetof(FEXCore::Core::CPUState, flags[0]) + Op->Flag)]); } DEF_OP(StoreFlag) { auto Op = IROp->C(); mov (rax, GetSrc(Op->Value.ID())); - mov(byte [STATE + (offsetof(FEXCore::Core::CPUState, flags[0]) + Op->Flag)], al); + + if (Op->Flag == 24 /* NZCV */) + mov(dword [STATE + (offsetof(FEXCore::Core::CPUState, flags[0]) + Op->Flag)], eax); + else + mov(byte [STATE + (offsetof(FEXCore::Core::CPUState, flags[0]) + Op->Flag)], al); } Xbyak::RegExp X86JITCore::GenerateModRM(Xbyak::Reg Base, IR::OrderedNodeWrapper Offset, IR::MemOffsetType OffsetType, uint8_t OffsetScale) const { diff --git a/External/FEXCore/include/FEXCore/Core/X86Enums.h b/External/FEXCore/include/FEXCore/Core/X86Enums.h index a28c942cd..21a36f071 100644 --- a/External/FEXCore/include/FEXCore/Core/X86Enums.h +++ b/External/FEXCore/include/FEXCore/Core/X86Enums.h @@ -74,6 +74,13 @@ enum X86RegLocation : uint32_t { RFLAG_VIP_LOC = 20, RFLAG_ID_LOC = 21, + // So we can implement arm64-like flag manipulaton on the interpreter/x86 jit.. + // SF/ZF/CF/OF packed into a 32-bit word, matching arm64's NZCV structure (not semantics). + RFLAG_NZCV_LOC = 24, + RFLAG_NZCV_1_LOC = 25, + RFLAG_NZCV_2_LOC = 26, + RFLAG_NZCV_3_LOC = 27, + // So we can share flag handling logic, we put x87 flags after RFLAGS X87FLAG_BASE = 32, X87FLAG_IE_LOC = 32,