PPU LLVM: new mptr/cptr format

This commit is contained in:
Nekotekina 2017-06-29 17:25:39 +03:00
parent 85f8a42bd2
commit 3c064439b3
5 changed files with 34 additions and 6 deletions

View File

@ -375,6 +375,7 @@ jit_compiler::jit_compiler(const std::unordered_map<std::string, std::uintptr_t>
if (m_link.empty())
{
// Auxiliary JIT (does not use custom memory manager, only writes the objects)
m_engine.reset(llvm::EngineBuilder(std::make_unique<llvm::Module>("null_", m_context))
.setErrorStr(&result)
.setOptLevel(llvm::CodeGenOpt::Aggressive)
@ -384,6 +385,7 @@ jit_compiler::jit_compiler(const std::unordered_map<std::string, std::uintptr_t>
}
else
{
// Primary JIT
auto mem = std::make_unique<MemoryManager>(m_link);
m_jit_el = std::make_unique<EventListener>(*mem);
@ -433,9 +435,9 @@ void jit_compiler::fin()
m_engine->finalizeObject();
}
u64 jit_compiler::get(const std::string & name)
u64 jit_compiler::get(const std::string& name)
{
return m_engine->getFunctionAddress(name);
return m_engine->getGlobalValueAddress(name);
}
std::unordered_map<std::string, u64> jit_compiler::add(std::unordered_map<std::string, std::string> data)

View File

@ -66,6 +66,12 @@ public:
{
return m_cpu;
}
// Check JIT purpose
bool is_primary() const
{
return !m_link.empty();
}
};
#endif

View File

@ -982,6 +982,9 @@ extern void ppu_initialize(const ppu_module& info)
// Worker threads
std::vector<std::thread> jthreads;
// Global variables (pointers) to initialize
std::vector<std::pair<std::string, void*>> globals;
// Split module into fragments <= 1 MiB
std::size_t fpos = 0;
@ -1078,6 +1081,9 @@ extern void ppu_initialize(const ppu_module& info)
break;
}
globals.emplace_back(fmt::format("__mptr%x", part.funcs[0].addr), vm::g_base_addr);
globals.emplace_back(fmt::format("__cptr%x", part.funcs[0].addr), vm::g_exec_addr);
// Check object file
if (fs::is_file(Emu.GetCachePath() + obj_name))
{
@ -1143,6 +1149,15 @@ extern void ppu_initialize(const ppu_module& info)
}
}
}
// Initialize global variables
for (auto& var : globals)
{
if (u64 addr = jit.get(var.first))
{
*reinterpret_cast<void**>(addr) = var.second;
}
}
#endif
}
@ -1277,6 +1292,7 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, co
{
out.flush();
LOG_ERROR(PPU, "LLVM: Verification failed for %s:\n%s", obj_name, result);
Emu.CallAfter([]{ Emu.Stop(); });
return;
}

View File

@ -19,7 +19,9 @@ PPUTranslator::PPUTranslator(LLVMContext& context, Module* module, const ppu_mod
, m_pure_attr(AttributeSet::get(m_context, AttributeSet::FunctionIndex, {Attribute::NoUnwind, Attribute::ReadNone}))
{
// Memory base
m_base = new GlobalVariable(*module, ArrayType::get(GetType<char>(), 0x100000000)->getPointerTo(), true, GlobalValue::ExternalLinkage, 0, "__mptr");
m_base = new GlobalVariable(*module, ArrayType::get(GetType<char>(), 0x100000000)->getPointerTo(), true, GlobalValue::ExternalLinkage, 0, fmt::format("__mptr%x", info.funcs[0].addr));
m_base->setInitializer(ConstantPointerNull::get(cast<PointerType>(m_base->getType()->getPointerElementType())));
m_base->setExternallyInitialized(true);
// Thread context struct (TODO: safer member access)
const u32 off0 = offset32(&ppu_thread::state);
@ -42,7 +44,9 @@ PPUTranslator::PPUTranslator(LLVMContext& context, Module* module, const ppu_mod
m_thread_type = StructType::create(m_context, thread_struct, "context_t");
// Callable
m_call = new GlobalVariable(*module, ArrayType::get(GetType<u32>(), 0x40000000)->getPointerTo(), true, GlobalValue::ExternalLinkage, 0, "__cptr");
m_call = new GlobalVariable(*module, ArrayType::get(GetType<u32>(), 0x40000000)->getPointerTo(), true, GlobalValue::ExternalLinkage, 0, fmt::format("__cptr%x", info.funcs[0].addr));
m_call->setInitializer(ConstantPointerNull::get(cast<PointerType>(m_call->getType()->getPointerElementType())));
m_call->setExternallyInitialized(true);
const auto md_name = MDString::get(m_context, "branch_weights");
const auto md_low = ValueAsMetadata::get(ConstantInt::get(GetType<u32>(), 1));

View File

@ -134,14 +134,14 @@ class PPUTranslator final //: public CPUTranslator
/* Variables */
// Memory base
llvm::Value* m_base;
llvm::GlobalVariable* m_base;
llvm::Value* m_base_loaded;
// Thread context
llvm::Value* m_thread;
// Callable functions
llvm::Value* m_call;
llvm::GlobalVariable* m_call;
// Main block
llvm::BasicBlock* m_body;