diff --git a/FEXCore/Source/Interface/Core/Core.cpp b/FEXCore/Source/Interface/Core/Core.cpp index 163d17950..0d451f1f4 100644 --- a/FEXCore/Source/Interface/Core/Core.cpp +++ b/FEXCore/Source/Interface/Core/Core.cpp @@ -613,7 +613,7 @@ ContextImpl::GenerateIR(FEXCore::Core::InternalThreadState* Thread, uint64_t Gue if (InstsInBlock == 0) { // Special case for an empty instruction block. - Thread->OpDispatcher->ExitFunction(Thread->OpDispatcher->_EntrypointOffset(GPRSize, Block.Entry - GuestRIP)); + Thread->OpDispatcher->ExitFunction(Thread->OpDispatcher->_InlineEntrypointOffset(GPRSize, Block.Entry - GuestRIP)); } for (size_t i = 0; i < InstsInBlock; ++i) { @@ -657,7 +657,7 @@ ContextImpl::GenerateIR(FEXCore::Core::InternalThreadState* Thread, uint64_t Gue Thread->OpDispatcher->SetCurrentCodeBlock(CodeWasChangedBlock); Thread->OpDispatcher->_ThreadRemoveCodeEntry(); - Thread->OpDispatcher->ExitFunction(Thread->OpDispatcher->_EntrypointOffset(GPRSize, InstAddress - GuestRIP)); + Thread->OpDispatcher->ExitFunction(Thread->OpDispatcher->_InlineEntrypointOffset(GPRSize, InstAddress - GuestRIP)); auto NextOpBlock = Thread->OpDispatcher->CreateNewCodeBlockAfter(CurrentBlock); @@ -723,7 +723,8 @@ ContextImpl::GenerateIR(FEXCore::Core::InternalThreadState* Thread, uint64_t Gue if (NeedsBlockEnd) { // We had some instructions. Early exit - Thread->OpDispatcher->ExitFunction(Thread->OpDispatcher->_EntrypointOffset(GPRSize, Block.Entry + BlockInstructionsLength - GuestRIP)); + Thread->OpDispatcher->ExitFunction( + Thread->OpDispatcher->_InlineEntrypointOffset(GPRSize, Block.Entry + BlockInstructionsLength - GuestRIP)); break; } diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index c1b5f66f6..6c8ea9299 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -534,7 +534,7 @@ void OpDispatchBuilder::CALLOp(OpcodeArgs) { if (NextRIP != TargetRIP) { // Store the RIP - ExitFunction(NewRIP, BranchHint::Call, ConstantPC, [&]() { + ExitRelocatedPC(Op, TargetOffset, BranchHint::Call, ConstantPC, [&]() { auto CallReturnJumpTarget = JumpTargets.find(NextRIP); if (CallReturnJumpTarget != JumpTargets.end() && CallReturnJumpTarget->second.IsEntryPoint) { return CallReturnJumpTarget->second.BlockEntry; @@ -742,10 +742,8 @@ void OpDispatchBuilder::CondJUMPOp(OpcodeArgs) { SetCurrentCodeBlock(JumpTarget); StartNewBlock(); - auto NewRIP = GetRelocatedPC(Op, TargetOffset); - // Store the new RIP - ExitFunction(NewRIP); + ExitRelocatedPC(Op, TargetOffset); } // Failure to take branch @@ -759,11 +757,8 @@ void OpDispatchBuilder::CondJUMPOp(OpcodeArgs) { SetCurrentCodeBlock(JumpTarget); StartNewBlock(); - // Leave block - auto RIPTargetConst = GetRelocatedPC(Op); - - // Store the new RIP - ExitFunction(RIPTargetConst); + // Leave block & store the new RIP + ExitRelocatedPC(Op); } } } @@ -798,10 +793,8 @@ void OpDispatchBuilder::CondJUMPRCXOp(OpcodeArgs) { SetCurrentCodeBlock(JumpTarget); StartNewBlock(); - auto NewRIP = GetRelocatedPC(Op, Op->Src[0].Data.Literal.Value); - // Store the new RIP - ExitFunction(NewRIP); + ExitRelocatedPC(Op, Op->Src[0].Data.Literal.Value); } // Failure to take branch @@ -815,11 +808,8 @@ void OpDispatchBuilder::CondJUMPRCXOp(OpcodeArgs) { SetCurrentCodeBlock(JumpTarget); StartNewBlock(); - // Leave block - auto RIPTargetConst = GetRelocatedPC(Op); - - // Store the new RIP - ExitFunction(RIPTargetConst); + // Leave block & store the new RIP + ExitRelocatedPC(Op); } } } @@ -872,10 +862,8 @@ void OpDispatchBuilder::LoopOp(OpcodeArgs) { SetCurrentCodeBlock(JumpTarget); StartNewBlock(); - auto NewRIP = GetRelocatedPC(Op, Op->Src[1].Data.Literal.Value); - // Store the new RIP - ExitFunction(NewRIP); + ExitRelocatedPC(Op, Op->Src[1].Data.Literal.Value); } // Failure to take branch @@ -889,11 +877,8 @@ void OpDispatchBuilder::LoopOp(OpcodeArgs) { SetCurrentCodeBlock(JumpTarget); StartNewBlock(); - // Leave block - auto RIPTargetConst = GetRelocatedPC(Op); - - // Store the new RIP - ExitFunction(RIPTargetConst); + // Leave block & store the new RIP + ExitRelocatedPC(Op); } } } @@ -937,10 +922,10 @@ void OpDispatchBuilder::JUMPOp(OpcodeArgs) { SetJumpTarget(Jump_, JumpTarget); SetCurrentCodeBlock(JumpTarget); StartNewBlock(); - ExitFunction(GetRelocatedPC(Op, TargetOffset)); + ExitRelocatedPC(Op, TargetOffset); } } else { - ExitFunction(GetRelocatedPC(Op, TargetOffset)); + ExitRelocatedPC(Op, TargetOffset); } } @@ -3895,7 +3880,7 @@ void OpDispatchBuilder::Finalize() { // We haven't emitted. Dump out to the dispatcher SetCurrentCodeBlock(Handler.second.BlockEntry); - ExitFunction(_EntrypointOffset(GPRSize, Handler.first - Entry)); + ExitFunction(_InlineEntrypointOffset(GPRSize, Handler.first - Entry)); } } @@ -4208,11 +4193,6 @@ Ref OpDispatchBuilder::LoadSource_WithOpSize(RegisterClassType Class, const X86T } } -Ref OpDispatchBuilder::GetRelocatedPC(const FEXCore::X86Tables::DecodedOp& Op, int64_t Offset) { - const auto GPRSize = GetGPROpSize(); - return _EntrypointOffset(GPRSize, Op->PC + Op->InstSize + Offset - Entry); -} - Ref OpDispatchBuilder::LoadGPRRegister(uint32_t GPR, IR::OpSize Size, uint8_t Offset, bool AllowUpperGarbage) { const auto GPRSize = GetGPROpSize(); if (Size == OpSize::iInvalid) { diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index e5727fe35..f996e7b85 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -201,8 +201,7 @@ public: const auto GPRSize = GetGPROpSize(); // If we don't have a jump target to a new block then we have to leave // Set the RIP to the next instruction and leave - auto RelocatedNextRIP = _EntrypointOffset(GPRSize, NextRIP - Entry); - ExitFunction(RelocatedNextRIP); + ExitFunction(_InlineEntrypointOffset(GPRSize, NextRIP - Entry)); } else if (it != JumpTargets.end()) { Jump(it->second.BlockEntry); return true; @@ -1520,7 +1519,23 @@ private: void StoreGPRRegister(uint32_t GPR, const Ref Src, IR::OpSize Size = OpSize::iInvalid, uint8_t Offset = 0); void StoreXMMRegister(uint32_t XMM, const Ref Src); - Ref GetRelocatedPC(const FEXCore::X86Tables::DecodedOp& Op, int64_t Offset = 0); + Ref _GetRelocatedPC(const FEXCore::X86Tables::DecodedOp& Op, int64_t Offset, bool Inline) { + const auto GPRSize = GetGPROpSize(); + const auto Offs = Op->PC + Op->InstSize + Offset - Entry; + return Inline ? _InlineEntrypointOffset(GPRSize, Offs) : _EntrypointOffset(GPRSize, Offs); + } + + Ref GetRelocatedPC(const FEXCore::X86Tables::DecodedOp& Op, int64_t Offset = 0) { + return _GetRelocatedPC(Op, Offset, false); + } + + void ExitRelocatedPC(const FEXCore::X86Tables::DecodedOp& Op, int64_t Offset = 0) { + ExitFunction(_GetRelocatedPC(Op, Offset, true /* Inline */)); + } + + void ExitRelocatedPC(const FEXCore::X86Tables::DecodedOp& Op, int64_t Offset, BranchHint Hint, Ref CallReturnAddress, Ref CallReturnBlock) { + ExitFunction(_GetRelocatedPC(Op, Offset, true /* Inline */), Hint, CallReturnAddress, CallReturnBlock); + } [[nodiscard]] static bool IsOperandMem(const X86Tables::DecodedOperand& Operand, bool Load) {