mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-24 16:01:15 +02:00
Merge pull request #207 from Sonicadvance1/interpreter_fallback
Adds support for interpreter fallback
This commit is contained in:
commit
2fd8e617ff
12 files changed
+63
-22
No files matched your search
+10
-1
@@ -386,6 +386,7 @@ namespace FEXCore::Context {
|
||||
|
||||
void Context::InitializeThreadData(FEXCore::Core::InternalThreadState *Thread) {
|
||||
Thread->CPUBackend->Initialize();
|
||||
Thread->IntBackend->Initialize();
|
||||
Thread->FallbackBackend->Initialize();
|
||||
|
||||
auto IRHandler = [this, Thread](uint64_t Addr, IR::IREmitter *IR) -> void {
|
||||
@@ -442,13 +443,19 @@ namespace FEXCore::Context {
|
||||
|
||||
// Create CPU backend
|
||||
switch (Config.Core) {
|
||||
case FEXCore::Config::CONFIG_INTERPRETER: Thread->CPUBackend.reset(FEXCore::CPU::CreateInterpreterCore(this)); break;
|
||||
case FEXCore::Config::CONFIG_INTERPRETER:
|
||||
Thread->CPUBackend.reset(FEXCore::CPU::CreateInterpreterCore(this));
|
||||
Thread->IntBackend = Thread->CPUBackend;
|
||||
break;
|
||||
case FEXCore::Config::CONFIG_IRJIT: Thread->CPUBackend.reset(FEXCore::CPU::CreateJITCore(this, Thread)); break;
|
||||
case FEXCore::Config::CONFIG_LLVMJIT: Thread->CPUBackend.reset(FEXCore::CPU::CreateLLVMCore(Thread)); break;
|
||||
case FEXCore::Config::CONFIG_CUSTOM: Thread->CPUBackend.reset(CustomCPUFactory(this, &Thread->State)); break;
|
||||
default: LogMan::Msg::A("Unknown core configuration");
|
||||
}
|
||||
|
||||
if (!Thread->IntBackend) {
|
||||
Thread->IntBackend.reset(FEXCore::CPU::CreateInterpreterCore(this));
|
||||
}
|
||||
Thread->FallbackBackend.reset(FallbackCPUFactory(this, &Thread->State));
|
||||
|
||||
LogMan::Throw::A(!Thread->FallbackBackend->NeedsOpDispatch(), "Fallback CPU backend must not require OpDispatch");
|
||||
@@ -485,6 +492,8 @@ namespace FEXCore::Context {
|
||||
void Context::ClearCodeCache(FEXCore::Core::InternalThreadState *Thread, uint64_t GuestRIP) {
|
||||
Thread->BlockCache->ClearCache();
|
||||
Thread->CPUBackend->ClearCache();
|
||||
Thread->IntBackend->ClearCache();
|
||||
|
||||
if (GuestRIP != 0) {
|
||||
auto IR = Thread->IRLists.find(GuestRIP)->second.release();
|
||||
Thread->IRLists.clear();
|
||||
|
||||
@@ -54,7 +54,8 @@ private:
|
||||
};
|
||||
|
||||
static void InterpreterExecution(FEXCore::Core::InternalThreadState *Thread) {
|
||||
InterpreterCore *Core = reinterpret_cast<InterpreterCore*>(Thread->CPUBackend.get());
|
||||
// IntBackend will always point to this interpreter object
|
||||
InterpreterCore *Core = reinterpret_cast<InterpreterCore*>(Thread->IntBackend.get());
|
||||
Core->ExecuteCode(Thread);
|
||||
}
|
||||
|
||||
|
||||
+10
-6
@@ -374,6 +374,16 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView<true> const
|
||||
uintptr_t ListBegin = CurrentIR->GetListData();
|
||||
uintptr_t DataBegin = CurrentIR->GetData();
|
||||
|
||||
auto HeaderIterator = CurrentIR->begin();
|
||||
IR::OrderedNodeWrapper *HeaderNodeWrapper = HeaderIterator();
|
||||
IR::OrderedNode *HeaderNode = HeaderNodeWrapper->GetNode(ListBegin);
|
||||
auto HeaderOp = HeaderNode->Op(DataBegin)->CW<FEXCore::IR::IROp_IRHeader>();
|
||||
LogMan::Throw::A(HeaderOp->Header.Op == IR::OP_IRHEADER, "First op wasn't IRHeader");
|
||||
|
||||
if (HeaderOp->ShouldInterpret) {
|
||||
return State->IntBackend->CompileCode(IR, DebugData);
|
||||
}
|
||||
|
||||
LogMan::Throw::A(RAPass->HasFullRA(), "Arm64 JIT only works with RA");
|
||||
|
||||
uint32_t SpillSlots = RAPass->SpillSlots();
|
||||
@@ -409,12 +419,6 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView<true> const
|
||||
sub(sp, sp, SpillSlots * 16);
|
||||
}
|
||||
|
||||
auto HeaderIterator = CurrentIR->begin();
|
||||
IR::OrderedNodeWrapper *HeaderNodeWrapper = HeaderIterator();
|
||||
IR::OrderedNode *HeaderNode = HeaderNodeWrapper->GetNode(ListBegin);
|
||||
auto HeaderOp = HeaderNode->Op(DataBegin)->CW<FEXCore::IR::IROp_IRHeader>();
|
||||
LogMan::Throw::A(HeaderOp->Header.Op == IR::OP_IRHEADER, "First op wasn't IRHeader");
|
||||
|
||||
IR::OrderedNode *BlockNode = HeaderOp->Blocks.GetNode(ListBegin);
|
||||
|
||||
while (1) {
|
||||
|
||||
@@ -235,6 +235,10 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView<true> const
|
||||
auto HeaderOp = HeaderNode->Op(DataBegin)->CW<FEXCore::IR::IROp_IRHeader>();
|
||||
LogMan::Throw::A(HeaderOp->Header.Op == IR::OP_IRHEADER, "First op wasn't IRHeader");
|
||||
|
||||
if (HeaderOp->ShouldInterpret) {
|
||||
return ThreadState->IntBackend->CompileCode(IR, DebugData);
|
||||
}
|
||||
|
||||
// Fairly excessive buffer range to make sure we don't overflow
|
||||
uint32_t BufferRange = SSACount * 16;
|
||||
if ((getSize() + BufferRange) > MAX_CODE_SIZE) {
|
||||
|
||||
+13
-9
@@ -3921,15 +3921,6 @@ void* FEXCore::CPU::LLVMJITCore::CompileCode(FEXCore::IR::IRListView<true> const
|
||||
|
||||
CurrentIR = IR;
|
||||
|
||||
#if DESTMAP_AS_MAP
|
||||
DestMap.clear();
|
||||
#else
|
||||
uintptr_t ListSize = CurrentIR->GetListSize();
|
||||
if (ListSize > DestMap.size()) {
|
||||
DestMap.resize(std::max(DestMap.size() * 2, ListSize));
|
||||
}
|
||||
#endif
|
||||
|
||||
uintptr_t ListBegin = CurrentIR->GetListData();
|
||||
uintptr_t DataBegin = CurrentIR->GetData();
|
||||
|
||||
@@ -3939,6 +3930,19 @@ void* FEXCore::CPU::LLVMJITCore::CompileCode(FEXCore::IR::IRListView<true> const
|
||||
auto HeaderOp = HeaderNode->Op(DataBegin)->CW<FEXCore::IR::IROp_IRHeader>();
|
||||
LogMan::Throw::A(HeaderOp->Header.Op == IR::OP_IRHEADER, "First op wasn't IRHeader");
|
||||
|
||||
if (HeaderOp->ShouldInterpret) {
|
||||
return ThreadState->IntBackend->CompileCode(IR, DebugData);
|
||||
}
|
||||
|
||||
#if DESTMAP_AS_MAP
|
||||
DestMap.clear();
|
||||
#else
|
||||
uintptr_t ListSize = CurrentIR->GetListSize();
|
||||
if (ListSize > DestMap.size()) {
|
||||
DestMap.resize(std::max(DestMap.size() * 2, ListSize));
|
||||
}
|
||||
#endif
|
||||
|
||||
std::ostringstream FunctionName;
|
||||
FunctionName << "Function_0x";
|
||||
FunctionName << std::hex << HeaderOp->Entry;
|
||||
|
||||
@@ -3348,7 +3348,8 @@ void OpDispatchBuilder::CreateJumpBlocks(std::vector<FEXCore::Frontend::Decoder:
|
||||
|
||||
void OpDispatchBuilder::BeginFunction(uint64_t RIP, std::vector<FEXCore::Frontend::Decoder::DecodedBlocks> const *Blocks) {
|
||||
Entry = RIP;
|
||||
auto IRHeader = _IRHeader(InvalidNode, RIP, 0);
|
||||
auto IRHeader = _IRHeader(InvalidNode, RIP, 0, false);
|
||||
Current_Header = IRHeader.first;
|
||||
CreateJumpBlocks(Blocks);
|
||||
|
||||
auto Block = GetNewJumpBlock(RIP);
|
||||
|
||||
@@ -346,6 +346,7 @@ public:
|
||||
|
||||
private:
|
||||
bool DecodeFailure{false};
|
||||
FEXCore::IR::IROp_IRHeader *Current_Header{};
|
||||
|
||||
OrderedNode *LoadSource(FEXCore::IR::RegisterClassType Class, FEXCore::X86Tables::DecodedOp const& Op, FEXCore::X86Tables::DecodedOperand const& Operand, uint32_t Flags, int8_t Align, bool LoadData = true, bool ForceLoad = false);
|
||||
OrderedNode *LoadSource_WithOpSize(FEXCore::IR::RegisterClassType Class, FEXCore::X86Tables::DecodedOp const& Op, FEXCore::X86Tables::DecodedOperand const& Operand, uint8_t OpSize, uint32_t Flags, int8_t Align, bool LoadData = true, bool ForceLoad = false);
|
||||
|
||||
+2
-1
@@ -58,7 +58,8 @@
|
||||
],
|
||||
"Args": [
|
||||
"uint64_t", "Entry",
|
||||
"uint32_t", "BlockCount"
|
||||
"uint32_t", "BlockCount",
|
||||
"bool", "ShouldInterpret"
|
||||
]
|
||||
},
|
||||
"CodeBlock": {
|
||||
|
||||
@@ -61,7 +61,7 @@ bool IRCompaction::Run(IREmitter *IREmit) {
|
||||
|
||||
// Zero is always zero(invalid)
|
||||
OldToNewRemap[0] = 0;
|
||||
auto LocalHeaderOp = LocalBuilder._IRHeader(OrderedNodeWrapper::WrapOffset(0).GetNode(ListBegin), HeaderOp->Entry, HeaderOp->BlockCount);
|
||||
auto LocalHeaderOp = LocalBuilder._IRHeader(OrderedNodeWrapper::WrapOffset(0).GetNode(ListBegin), HeaderOp->Entry, HeaderOp->BlockCount, HeaderOp->ShouldInterpret);
|
||||
OldToNewRemap[HeaderNode->Wrapped(ListBegin).ID()] = LocalHeaderOp.Node->Wrapped(LocalListBegin).ID();
|
||||
|
||||
struct CodeBlockData {
|
||||
|
||||
@@ -1220,6 +1220,21 @@ namespace FEXCore::IR {
|
||||
bool ConstrainedRAPass::Run(IREmitter *IREmit) {
|
||||
bool Changed = false;
|
||||
|
||||
auto IR = IREmit->ViewIR();
|
||||
uintptr_t ListBegin = IR.GetListData();
|
||||
uintptr_t DataBegin = IR.GetData();
|
||||
|
||||
auto Begin = IR.begin();
|
||||
auto Op = Begin();
|
||||
|
||||
IR::OrderedNode *RealNode = Op->GetNode(ListBegin);
|
||||
auto HeaderOp = RealNode->Op(DataBegin)->CW<FEXCore::IR::IROp_IRHeader>();
|
||||
LogMan::Throw::A(HeaderOp->Header.Op == IR::OP_IRHEADER, "First op wasn't IRHeader");
|
||||
|
||||
if (HeaderOp->ShouldInterpret) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SpillSlotCount = 0;
|
||||
Graph->SpillStack.clear();
|
||||
|
||||
|
||||
@@ -49,7 +49,8 @@ namespace FEXCore::Core {
|
||||
|
||||
std::unique_ptr<FEXCore::IR::OpDispatchBuilder> OpDispatcher;
|
||||
|
||||
std::unique_ptr<FEXCore::CPU::CPUBackend> CPUBackend;
|
||||
std::shared_ptr<FEXCore::CPU::CPUBackend> CPUBackend;
|
||||
std::shared_ptr<FEXCore::CPU::CPUBackend> IntBackend;
|
||||
std::unique_ptr<FEXCore::CPU::CPUBackend> FallbackBackend;
|
||||
|
||||
std::unique_ptr<FEXCore::BlockCache> BlockCache;
|
||||
|
||||
@@ -363,7 +363,7 @@ namespace FEX::IRLoader {
|
||||
if (!CheckPrintError(Def, CodeBlockCount.first)) return false;
|
||||
|
||||
EntryRIP = Entry.second;
|
||||
IRHeader = _IRHeader(InvalidNode, Entry.second, CodeBlockCount.second);
|
||||
IRHeader = _IRHeader(InvalidNode, Entry.second, CodeBlockCount.second, false);
|
||||
}
|
||||
|
||||
// Spin through the blocks and generate basic block ops
|
||||
|
||||
Reference in new issue
Block a user