diff --git a/FEXCore/Source/Interface/Core/Core.cpp b/FEXCore/Source/Interface/Core/Core.cpp index 56c8b900b..a4e52061f 100644 --- a/FEXCore/Source/Interface/Core/Core.cpp +++ b/FEXCore/Source/Interface/Core/Core.cpp @@ -614,6 +614,20 @@ ContextImpl::GenerateIR(FEXCore::Core::InternalThreadState* Thread, uint64_t Gue DecodedInfo = &Block.DecodedInstructions[i]; bool IsLocked = DecodedInfo->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_LOCK; + // Do a partial register cache flush before every instruction. This + // prevents cross-instruction static register caching, while allowing + // context load/stores to be optimized within a block. Theoretically, + // this flush is not required for correctness, all mandatory flushes are + // included in instruction-specific handlers. Instead, this is a blunt + // heuristic to make the register cache less aggressive, as the current + // RA generates bad code in common cases with tied registers otherwise. + // + // However, it makes our exception handling behaviour more predictable. + // It is potentially correctness bearing in that sense, but that is a + // side effect here and (if that behaviour is required) we should handle + // that more explicitly later. + Thread->OpDispatcher->FlushRegisterCache(true); + if (ExtendedDebugInfo || Thread->OpDispatcher->CanHaveSideEffects(TableInfo, DecodedInfo)) { Thread->OpDispatcher->_GuestOpcode(Block.Entry + BlockInstructionsLength - GuestRIP); } diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 509de59ca..fd1a6238b 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -3366,8 +3366,8 @@ void OpDispatchBuilder::CMPSOp(OpcodeArgs) { auto Src2 = _LoadMem(GPRClass, Size, Dest_RSI, Size); // We'll calculate PF/AF after the loop, so use them as temporaries here. - _StoreRegister(Src1, Core::CPUState::PF_AS_GREG, GPRClass, CTX->GetGPRSize()); - _StoreRegister(Src2, Core::CPUState::AF_AS_GREG, GPRClass, CTX->GetGPRSize()); + StoreRegister(Core::CPUState::PF_AS_GREG, false, Src1); + StoreRegister(Core::CPUState::AF_AS_GREG, false, Src2); Ref TailCounter = LoadGPRRegister(X86State::REG_RCX); @@ -3406,8 +3406,8 @@ void OpDispatchBuilder::CMPSOp(OpcodeArgs) { // Make sure to start a new block after ending this one { // Grab the sources from the last iteration so we can set flags. - auto Src1 = _LoadRegister(Core::CPUState::PF_AS_GREG, GPRClass, CTX->GetGPRSize()); - auto Src2 = _LoadRegister(Core::CPUState::AF_AS_GREG, GPRClass, CTX->GetGPRSize()); + auto Src1 = LoadGPR(Core::CPUState::PF_AS_GREG); + auto Src2 = LoadGPR(Core::CPUState::AF_AS_GREG); GenerateFlags_SUB(Op, Src2, Src1); } auto Jump_ = Jump(); @@ -4362,7 +4362,7 @@ Ref OpDispatchBuilder::LoadSource_WithOpSize(RegisterClassType Class, const X86T const auto highIndex = Operand.Data.GPR.HighBits ? 1 : 0; if (gpr >= FEXCore::X86State::REG_MM_0) { - A.Base = _LoadContext(OpSize, FPRClass, offsetof(FEXCore::Core::CPUState, mm[gpr - FEXCore::X86State::REG_MM_0])); + A.Base = LoadContext(MM0Index + gpr - FEXCore::X86State::REG_MM_0); } else if (gpr >= FEXCore::X86State::REG_XMM_0) { const auto gprIndex = gpr - X86State::REG_XMM_0; @@ -4399,7 +4399,7 @@ Ref OpDispatchBuilder::LoadGPRRegister(uint32_t GPR, int8_t Size, uint8_t Offset if (Size == -1) { Size = GPRSize; } - Ref Reg = _LoadRegister(GPR, GPRClass, GPRSize); + Ref Reg = LoadGPR(GPR); if ((!AllowUpperGarbage && (Size != GPRSize)) || Offset != 0) { // Extract the subregister if requested. @@ -4413,11 +4413,6 @@ Ref OpDispatchBuilder::LoadGPRRegister(uint32_t GPR, int8_t Size, uint8_t Offset return Reg; } -Ref OpDispatchBuilder::LoadXMMRegister(uint32_t XMM) { - const auto VectorSize = CTX->HostFeatures.SupportsSVE256 ? 32 : 16; - return _LoadRegister(XMM, FPRClass, VectorSize); -} - void OpDispatchBuilder::StoreGPRRegister(uint32_t GPR, const Ref Src, int8_t Size, uint8_t Offset) { const uint8_t GPRSize = CTX->GetGPRSize(); if (Size == -1) { @@ -4427,16 +4422,14 @@ void OpDispatchBuilder::StoreGPRRegister(uint32_t GPR, const Ref Src, int8_t Siz Ref Reg = Src; if (Size != GPRSize || Offset != 0) { // Need to do an insert if not automatic size or zero offset. - Reg = LoadGPRRegister(GPR); - Reg = _Bfi(IR::SizeToOpSize(GPRSize), Size * 8, Offset, Reg, Src); + Reg = _Bfi(IR::SizeToOpSize(GPRSize), Size * 8, Offset, LoadGPRRegister(GPR), Src); } - _StoreRegister(Reg, GPR, GPRClass, GPRSize); + StoreRegister(GPR, false, Reg); } void OpDispatchBuilder::StoreXMMRegister(uint32_t XMM, const Ref Src) { - const auto VectorSize = CTX->HostFeatures.SupportsSVE256 ? 32 : 16; - _StoreRegister(Src, XMM, FPRClass, VectorSize); + StoreRegister(XMM, true, Src); } Ref OpDispatchBuilder::LoadSource(RegisterClassType Class, const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand, @@ -4455,7 +4448,8 @@ void OpDispatchBuilder::StoreResult_WithOpSize(FEXCore::IR::RegisterClassType Cl const auto gpr = Operand.Data.GPR.GPR; if (gpr >= FEXCore::X86State::REG_MM_0) { - _StoreContext(OpSize, Class, Src, offsetof(FEXCore::Core::CPUState, mm[gpr - FEXCore::X86State::REG_MM_0])); + LOGMAN_THROW_A_FMT(OpSize == 8, "full"); + StoreContext(MM0Index + gpr - FEXCore::X86State::REG_MM_0, Src); } else if (gpr >= FEXCore::X86State::REG_XMM_0) { const auto gprIndex = gpr - X86State::REG_XMM_0; const auto VectorSize = CTX->HostFeatures.SupportsSVE256 ? 32 : 16; @@ -4543,6 +4537,8 @@ void OpDispatchBuilder::ResetWorkingList() { DecodeFailure = false; ShouldDump = false; CurrentCodeBlock = nullptr; + RegCache.Written = 0; + RegCache.Cached = 0; } void OpDispatchBuilder::UnhandledOp(OpcodeArgs) { diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 4dc232f53..e8fb400bf 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -1264,6 +1265,50 @@ public: } } + void FlushRegisterCache(bool SRAOnly = false) { + CalculateDeferredFlags(); + + const uint8_t GPRSize = CTX->GetGPRSize(); + const auto VectorSize = CTX->HostFeatures.SupportsSVE256 ? 32 : 16; + + // Write backwards. This is a heuristic to improve coalescing, since we + // often copy from (low) fixed GPRs to (high) PF/AF for celebrity + // instructions like "add rax, 1". This hack will go away with clauses. + uint64_t Bits = RegCache.Written; + + // We have an SRA only mode that exists as a hack to make register caching + // less aggressive. We should get rid of this once RA can take it. + uint64_t Mask = ~0ULL; + + if (SRAOnly) { + const uint64_t GPRMask = ((1ull << (AFIndex - GPR0Index + 1)) - 1) << GPR0Index; + const uint64_t FPRMask = ((1ull << (FPR15Index - FPR0Index + 1)) - 1) << FPR0Index; + + Mask &= (GPRMask | FPRMask); + Bits &= Mask; + } + + while (Bits != 0) { + uint32_t Index = 63 - std::countl_zero(Bits); + Ref Value = RegCache.Value[Index]; + + if (Index >= GPR0Index && Index <= AFIndex) { + _StoreRegister(Value, Index - GPR0Index, GPRClass, GPRSize); + } else if (Index >= FPR0Index && Index <= FPR15Index) { + _StoreRegister(Value, Index - FPR0Index, FPRClass, VectorSize); + } else if (Index == DFIndex) { + _StoreFlag(Value, X86State::RFLAG_DF_RAW_LOC); + } else { + _StoreContext(CacheIndexToSize(Index), CacheIndexClass(Index), Value, CacheIndexToContextOffset(Index)); + } + + Bits &= ~(1ull << Index); + } + + RegCache.Written &= ~Mask; + RegCache.Cached &= ~Mask; + } + protected: void SaveNZCV(IROps Op = OP_DUMMY) override { /* Some opcodes are conservatively marked as clobbering flags, but in fact @@ -1481,7 +1526,6 @@ private: void UpdatePrefixFromSegment(Ref Segment, uint32_t SegmentReg); Ref LoadGPRRegister(uint32_t GPR, int8_t Size = -1, uint8_t Offset = 0, bool AllowUpperGarbage = false); - Ref LoadXMMRegister(uint32_t XMM); void StoreGPRRegister(uint32_t GPR, const Ref Src, int8_t Size = -1, uint8_t Offset = 0); void StoreXMMRegister(uint32_t XMM, const Ref Src); @@ -1697,9 +1741,9 @@ private: if (IsNZCV(BitOffset)) { InsertNZCV(BitOffset, Value, ValueOffset, MustMask); } else if (BitOffset == FEXCore::X86State::RFLAG_PF_RAW_LOC) { - _StoreRegister(Value, Core::CPUState::PF_AS_GREG, GPRClass, CTX->GetGPRSize()); + StoreRegister(Core::CPUState::PF_AS_GREG, false, Value); } else if (BitOffset == FEXCore::X86State::RFLAG_AF_RAW_LOC) { - _StoreRegister(Value, Core::CPUState::AF_AS_GREG, GPRClass, CTX->GetGPRSize()); + StoreRegister(Core::CPUState::AF_AS_GREG, false, Value); } else { if (ValueOffset || MustMask) { Value = _Bfe(OpSize::i32Bit, 1, ValueOffset, Value); @@ -1707,10 +1751,10 @@ private: // For DF, we need to transform 0/1 into 1/-1 if (BitOffset == FEXCore::X86State::RFLAG_DF_RAW_LOC) { - Value = _SubShift(OpSize::i64Bit, _Constant(1), Value, ShiftType::LSL, 1); + StoreDF(_SubShift(OpSize::i64Bit, _Constant(1), Value, ShiftType::LSL, 1)); + } else { + _StoreFlag(Value, BitOffset); } - - _StoreFlag(Value, BitOffset); } } @@ -1726,10 +1770,13 @@ private: void InvalidateAF() { _InvalidateFlags((1u << X86State::RFLAG_AF_RAW_LOC)); + InvalidateReg(Core::CPUState::AF_AS_GREG); } void InvalidatePF_AF() { _InvalidateFlags((1u << X86State::RFLAG_PF_RAW_LOC) | (1u << X86State::RFLAG_AF_RAW_LOC)); + InvalidateReg(Core::CPUState::PF_AS_GREG); + InvalidateReg(Core::CPUState::AF_AS_GREG); } CondClassType CondForNZCVBit(unsigned BitOffset, bool Invert) { @@ -1746,8 +1793,114 @@ private: } } - void FlushRegisterCache() { - CalculateDeferredFlags(); + /* Layout of cache indices. We use a single 64-bit bitmask for the cache */ + static const int GPR0Index = 0; + static const int GPR15Index = 15; + static const int PFIndex = 16; + static const int AFIndex = 17; + /* Gap 18..19 */ + static const int MM0Index = 20; + static const int MM7Index = 27; + static const int AbridgedFTWIndex = 28; + /* Gap 29..30 */ + static const int DFIndex = 31; + static const int FPR0Index = 32; + static const int FPR15Index = 47; + static const int AVXHigh0Index = 48; + static const int AVXHigh15Index = 63; + + int CacheIndexToContextOffset(int Index) { + switch (Index) { + case MM0Index ... MM7Index: return offsetof(FEXCore::Core::CPUState, mm[Index - MM0Index]); + case AVXHigh0Index ... AVXHigh15Index: return offsetof(FEXCore::Core::CPUState, avx_high[Index - AVXHigh0Index][0]); + case AbridgedFTWIndex: return offsetof(FEXCore::Core::CPUState, AbridgedFTW); + default: return -1; + } + } + + RegisterClassType CacheIndexClass(int Index) { + if ((Index >= MM0Index && Index <= MM7Index) || Index >= FPR0Index) { + return FPRClass; + } else { + return GPRClass; + } + } + + unsigned CacheIndexToSize(int Index) { + if (Index >= AVXHigh0Index) { + return 16; + } else if (Index <= MM7Index) { + return 8; + } else { + return 1; + } + } + + struct { + uint64_t Cached; + uint64_t Written; + Ref Value[64]; + } RegCache {}; + + void InvalidateReg(uint8_t Index) { + uint64_t Bit = (1ull << (uint64_t)Index); + RegCache.Cached &= ~Bit; + RegCache.Written &= ~Bit; + } + + Ref LoadRegCache(uint64_t Offset, uint8_t Index, RegisterClassType RegClass, uint8_t Size) { + LOGMAN_THROW_AA_FMT(Index < 64, "valid index"); + uint64_t Bit = (1ull << (uint64_t)Index); + + if (!(RegCache.Cached & Bit)) { + if (Index == DFIndex) { + RegCache.Value[Index] = _LoadDF(); + } else if ((Index >= MM0Index && Index <= AbridgedFTWIndex) || Index >= AVXHigh0Index) { + RegCache.Value[Index] = _LoadContext(Size, RegClass, Offset); + } else { + RegCache.Value[Index] = _LoadRegister(Offset, RegClass, Size); + } + + RegCache.Cached |= Bit; + } + + return RegCache.Value[Index]; + } + + Ref LoadGPR(uint8_t Reg) { + return LoadRegCache(Reg, GPR0Index + Reg, GPRClass, CTX->GetGPRSize()); + } + + Ref LoadContext(uint8_t Index) { + return LoadRegCache(CacheIndexToContextOffset(Index), Index, CacheIndexClass(Index), CacheIndexToSize(Index)); + } + + Ref LoadXMMRegister(uint8_t Reg) { + const auto Size = CTX->HostFeatures.SupportsSVE256 ? 32 : 16; + return LoadRegCache(Reg, FPR0Index + Reg, FPRClass, Size); + } + + Ref LoadDF() { + return LoadGPR(DFIndex); + } + + void StoreContext(uint8_t Index, Ref Value) { + LOGMAN_THROW_AA_FMT(Index < 64, "valid index"); + LOGMAN_THROW_AA_FMT(Value != InvalidNode, "storing valid"); + + uint64_t Bit = (1ull << (uint64_t)Index); + + RegCache.Value[Index] = Value; + RegCache.Cached |= Bit; + RegCache.Written |= Bit; + } + + void StoreRegister(uint8_t Reg, bool FPR, Ref Value) { + StoreContext(Reg + (FPR ? FPR0Index : GPR0Index), Value); + } + + void StoreDF(Ref Value) { + StoreContext(DFIndex, Value); } Ref GetRFLAG(unsigned BitOffset, bool Invert = false) { @@ -1766,12 +1919,12 @@ private: return _NZCVSelect(OpSize::i32Bit, CondForNZCVBit(BitOffset, Invert), _Constant(1), _Constant(0)); } } else if (BitOffset == FEXCore::X86State::RFLAG_PF_RAW_LOC) { - return _LoadRegister(Core::CPUState::PF_AS_GREG, GPRClass, CTX->GetGPRSize()); + return LoadGPR(Core::CPUState::PF_AS_GREG); } else if (BitOffset == FEXCore::X86State::RFLAG_AF_RAW_LOC) { - return _LoadRegister(Core::CPUState::AF_AS_GREG, GPRClass, CTX->GetGPRSize()); + return LoadGPR(Core::CPUState::AF_AS_GREG); } else if (BitOffset == FEXCore::X86State::RFLAG_DF_RAW_LOC) { // Recover the sign bit, it is the logical DF value - return _Lshr(OpSize::i64Bit, _LoadDF(), _Constant(63)); + return _Lshr(OpSize::i64Bit, LoadDF(), _Constant(63)); } else { return _LoadFlag(BitOffset); } @@ -1779,7 +1932,7 @@ private: // Returns (DF ? -Size : Size) Ref LoadDir(const unsigned Size) { - auto Dir = _LoadDF(); + auto Dir = LoadDF(); auto Shift = FEXCore::ilog2(Size); if (Shift) { @@ -1793,7 +1946,7 @@ private: Ref OffsetByDir(Ref X, const unsigned Size) { auto Shift = FEXCore::ilog2(Size); - return _AddShift(OpSize::i64Bit, X, _LoadDF(), ShiftType::LSL, Shift); + return _AddShift(OpSize::i64Bit, X, LoadDF(), ShiftType::LSL, Shift); } // Compares two floats and sets flags for a COMISS instruction diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/AVX_128.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/AVX_128.cpp index fb916b7d2..9417c9781 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/AVX_128.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/AVX_128.cpp @@ -530,17 +530,17 @@ void OpDispatchBuilder::AVX128_StoreResult_WithOpSize(FEXCore::X86Tables::Decode Ref OpDispatchBuilder::AVX128_LoadXMMRegister(uint32_t XMM, bool High) { if (High) { - return _LoadContext(16, FPRClass, offsetof(FEXCore::Core::CPUState, avx_high[XMM][0])); + return LoadContext(AVXHigh0Index + XMM); } else { - return _LoadRegister(XMM, FPRClass, 16); + return LoadXMMRegister(XMM); } } void OpDispatchBuilder::AVX128_StoreXMMRegister(uint32_t XMM, const Ref Src, bool High) { if (High) { - _StoreContext(16, FPRClass, Src, offsetof(FEXCore::Core::CPUState, avx_high[XMM][0])); + StoreContext(AVXHigh0Index + XMM, Src); } else { - _StoreRegister(Src, XMM, FPRClass, 16); + StoreXMMRegister(XMM, Src); } } diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp index 5f2cfb255..7f591d4f6 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp @@ -2644,8 +2644,7 @@ void OpDispatchBuilder::SaveX87State(OpcodeArgs, Ref MemBase) { { // Abridged FTW - auto AbridgedFTW = _LoadContext(1, GPRClass, offsetof(FEXCore::Core::CPUState, AbridgedFTW)); - _StoreMem(GPRClass, 1, AbridgedFTW, MemBase, _Constant(4), 2, MEM_OFFSET_SXTX, 1); + _StoreMem(GPRClass, 1, LoadContext(AbridgedFTWIndex), MemBase, _Constant(4), 2, MEM_OFFSET_SXTX, 1); } // BYTE | 0 1 | 2 3 | 4 | 5 | 6 7 | 8 9 | a b | c d | e f | @@ -2693,7 +2692,7 @@ void OpDispatchBuilder::SaveX87State(OpcodeArgs, Ref MemBase) { // If OSFXSR bit in CR4 is not set than FXSAVE /may/ not save the XMM registers // This is implementation dependent for (uint32_t i = 0; i < Core::CPUState::NUM_MMS; ++i) { - Ref MMReg = _LoadContext(16, FPRClass, offsetof(FEXCore::Core::CPUState, mm[i])); + Ref MMReg = LoadContext(MM0Index + i); _StoreMem(FPRClass, 16, MMReg, MemBase, _Constant(i * 16 + 32), 16, MEM_OFFSET_SXTX, 1); } @@ -2820,13 +2819,12 @@ void OpDispatchBuilder::RestoreX87State(Ref MemBase) { { // Abridged FTW - auto NewAbridgedFTW = _LoadMem(GPRClass, 1, MemBase, _Constant(4), 2, MEM_OFFSET_SXTX, 1); - _StoreContext(1, GPRClass, NewAbridgedFTW, offsetof(FEXCore::Core::CPUState, AbridgedFTW)); + StoreContext(AbridgedFTWIndex, _LoadMem(GPRClass, 1, MemBase, _Constant(4), 2, MEM_OFFSET_SXTX, 1)); } for (uint32_t i = 0; i < Core::CPUState::NUM_MMS; ++i) { auto MMReg = _LoadMem(FPRClass, 16, MemBase, _Constant(i * 16 + 32), 16, MEM_OFFSET_SXTX, 1); - _StoreContext(16, FPRClass, MMReg, offsetof(FEXCore::Core::CPUState, mm[i])); + StoreContext(MM0Index + i, MMReg); } } @@ -2865,7 +2863,7 @@ void OpDispatchBuilder::DefaultX87State(OpcodeArgs) { // all of the ST0-7/MM0-7 registers to zero. Ref ZeroVector = LoadZeroVector(Core::CPUState::MM_REG_SIZE); for (uint32_t i = 0; i < Core::CPUState::NUM_MMS; ++i) { - _StoreContext(16, FPRClass, ZeroVector, offsetof(FEXCore::Core::CPUState, mm[i])); + StoreContext(MM0Index + i, ZeroVector); } } diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp index 3699c0925..3e1db6356 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp @@ -31,14 +31,14 @@ Ref OpDispatchBuilder::GetX87Top() { void OpDispatchBuilder::SetX87ValidTag(Ref Value, bool Valid) { // if we are popping then we must first mark this location as empty - Ref AbridgedFTW = _LoadContext(1, GPRClass, offsetof(FEXCore::Core::CPUState, AbridgedFTW)); + Ref AbridgedFTW = LoadContext(AbridgedFTWIndex); Ref RegMask = _Lshl(OpSize::i32Bit, _Constant(1), Value); Ref NewAbridgedFTW = Valid ? _Or(OpSize::i32Bit, AbridgedFTW, RegMask) : _Andn(OpSize::i32Bit, AbridgedFTW, RegMask); - _StoreContext(1, GPRClass, NewAbridgedFTW, offsetof(FEXCore::Core::CPUState, AbridgedFTW)); + StoreContext(AbridgedFTWIndex, NewAbridgedFTW); } Ref OpDispatchBuilder::GetX87ValidTag(Ref Value) { - Ref AbridgedFTW = _LoadContext(1, GPRClass, offsetof(FEXCore::Core::CPUState, AbridgedFTW)); + Ref AbridgedFTW = LoadContext(AbridgedFTWIndex); return _And(OpSize::i32Bit, _Lshr(OpSize::i32Bit, AbridgedFTW, Value), _Constant(1)); } @@ -51,8 +51,7 @@ Ref OpDispatchBuilder::GetX87Tag(Ref Value, Ref AbridgedFTW) { } Ref OpDispatchBuilder::GetX87Tag(Ref Value) { - Ref AbridgedFTW = _LoadContext(1, GPRClass, offsetof(FEXCore::Core::CPUState, AbridgedFTW)); - return GetX87Tag(Value, AbridgedFTW); + return GetX87Tag(Value, LoadContext(AbridgedFTWIndex)); } void OpDispatchBuilder::SetX87FTW(Ref FTW) { @@ -70,11 +69,11 @@ void OpDispatchBuilder::SetX87FTW(Ref FTW) { } } - _StoreContext(1, GPRClass, NewAbridgedFTW, offsetof(FEXCore::Core::CPUState, AbridgedFTW)); + StoreContext(AbridgedFTWIndex, NewAbridgedFTW); } Ref OpDispatchBuilder::GetX87FTW() { - Ref AbridgedFTW = _LoadContext(1, GPRClass, offsetof(FEXCore::Core::CPUState, AbridgedFTW)); + Ref AbridgedFTW = LoadContext(AbridgedFTWIndex); Ref FTW = _Constant(0); for (int i = 0; i < 8; i++) { @@ -154,7 +153,6 @@ void OpDispatchBuilder::FLD(OpcodeArgs) { SetX87Top(top); // Write to ST[TOP] _StoreContextIndexed(converted, top, 16, MMBaseOffset(), 16, FPRClass); - //_StoreContext(converted, 16, offsetof(FEXCore::Core::CPUState, mm[7][0])); } template void OpDispatchBuilder::FLD<32>(OpcodeArgs); @@ -644,7 +642,7 @@ void OpDispatchBuilder::FNINIT(OpcodeArgs) { SetRFLAG(Zero); // Tags all get marked as invalid - _StoreContext(1, GPRClass, Zero, offsetof(FEXCore::Core::CPUState, AbridgedFTW)); + StoreContext(AbridgedFTWIndex, Zero); } template @@ -1215,7 +1213,7 @@ void OpDispatchBuilder::X87FCMOV(OpcodeArgs) { void OpDispatchBuilder::X87EMMS(OpcodeArgs) { // Tags all get set to 0b11 - _StoreContext(1, GPRClass, _Constant(0), offsetof(FEXCore::Core::CPUState, AbridgedFTW)); + StoreContext(AbridgedFTWIndex, _Constant(0)); } void OpDispatchBuilder::X87FFREE(OpcodeArgs) { diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp index 96d2f3577..a746e5dc0 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp @@ -60,7 +60,7 @@ void OpDispatchBuilder::FNINITF64(OpcodeArgs) { SetRFLAG(Zero); // Tags all get marked as invalid - _StoreContext(1, GPRClass, Zero, offsetof(FEXCore::Core::CPUState, AbridgedFTW)); + StoreContext(AbridgedFTWIndex, Zero); } void OpDispatchBuilder::X87LDENVF64(OpcodeArgs) {