Merge pull request #207 from Sonicadvance1/interpreter_fallback

Adds support for interpreter fallback
This commit is contained in:
Stefanos Kornilios Mitsis Poiitidis authored and GitHub committed 2020-05-27 14:20:58 +03:00
commit 2fd8e617ff
12 files changed
+63 -22

No files matched your search

+10 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+1 -1
View File
@@ -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