mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-05 06:21:26 +12:00
PPU LLVM: Thread context argument
This commit is contained in:
parent
2c10348408
commit
73ea020525
3 changed files with 30 additions and 38 deletions
|
@ -33,7 +33,7 @@ struct ppu_addr_hash
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::unordered_map<u32, void(*)(), ppu_addr_hash> s_ppu_compiled;
|
static std::unordered_map<u32, void(*)(PPUThread&), ppu_addr_hash> s_ppu_compiled;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ void PPUThread::cpu_task()
|
||||||
|
|
||||||
if (found != s_ppu_compiled.end())
|
if (found != s_ppu_compiled.end())
|
||||||
{
|
{
|
||||||
return found->second();
|
return found->second(*this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,7 +430,7 @@ static std::vector<RUNTIME_FUNCTION> s_unwind;
|
||||||
|
|
||||||
struct MemoryManager final : llvm::RTDyldMemoryManager
|
struct MemoryManager final : llvm::RTDyldMemoryManager
|
||||||
{
|
{
|
||||||
static PPUThread* context(u64 addr)
|
static PPUThread* context(u64 addr) // Unused
|
||||||
{
|
{
|
||||||
//trace(addr);
|
//trace(addr);
|
||||||
return static_cast<PPUThread*>(get_current_cpu_thread());
|
return static_cast<PPUThread*>(get_current_cpu_thread());
|
||||||
|
@ -447,16 +447,14 @@ struct MemoryManager final : llvm::RTDyldMemoryManager
|
||||||
LOG_NOTICE(PPU, "Trace: 0x%llx", addr);
|
LOG_NOTICE(PPU, "Trace: 0x%llx", addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hack(u32 index)
|
static void hlecall(PPUThread& ppu, u32 index)
|
||||||
{
|
{
|
||||||
PPUThread& ppu = static_cast<PPUThread&>(*get_current_cpu_thread());
|
|
||||||
ppu_execute_function(ppu, index);
|
ppu_execute_function(ppu, index);
|
||||||
if (ppu.state.load() && ppu.check_status()) throw cpu_state::ret; // Temporarily
|
if (ppu.state.load() && ppu.check_status()) throw cpu_state::ret; // Temporarily
|
||||||
}
|
}
|
||||||
|
|
||||||
static void syscall(u64 code)
|
static void syscall(PPUThread& ppu, u64 code)
|
||||||
{
|
{
|
||||||
PPUThread& ppu = static_cast<PPUThread&>(*get_current_cpu_thread());
|
|
||||||
ppu_execute_syscall(ppu, code);
|
ppu_execute_syscall(ppu, code);
|
||||||
if (ppu.state.load() && ppu.check_status()) throw cpu_state::ret; // Temporarily
|
if (ppu.state.load() && ppu.check_status()) throw cpu_state::ret; // Temporarily
|
||||||
}
|
}
|
||||||
|
@ -466,13 +464,13 @@ struct MemoryManager final : llvm::RTDyldMemoryManager
|
||||||
return (u32)get_timebased_time();
|
return (u32)get_timebased_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void call(u32 addr)
|
static void call(PPUThread& ppu, u32 addr)
|
||||||
{
|
{
|
||||||
const auto found = s_ppu_compiled.find(addr);
|
const auto found = s_ppu_compiled.find(addr);
|
||||||
|
|
||||||
if (found != s_ppu_compiled.end())
|
if (found != s_ppu_compiled.end())
|
||||||
{
|
{
|
||||||
return found->second();
|
return found->second(ppu);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto op = vm::read32(addr).value();
|
const auto op = vm::read32(addr).value();
|
||||||
|
@ -481,7 +479,7 @@ struct MemoryManager final : llvm::RTDyldMemoryManager
|
||||||
// Allow HLE callbacks without compiling them
|
// Allow HLE callbacks without compiling them
|
||||||
if (itype == ppu_itype::HACK && vm::read32(addr + 4) == ppu_instructions::BLR())
|
if (itype == ppu_itype::HACK && vm::read32(addr + 4) == ppu_instructions::BLR())
|
||||||
{
|
{
|
||||||
return hack(op & 0x3ffffff);
|
return hlecall(ppu, op & 0x3ffffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
trap(addr);
|
trap(addr);
|
||||||
|
@ -683,10 +681,9 @@ struct MemoryManager final : llvm::RTDyldMemoryManager
|
||||||
std::unordered_map<std::string, u64> table
|
std::unordered_map<std::string, u64> table
|
||||||
{
|
{
|
||||||
{ "__memory", (u64)vm::base(0) },
|
{ "__memory", (u64)vm::base(0) },
|
||||||
{ "__context", (u64)&context },
|
|
||||||
{ "__trap", (u64)&trap },
|
{ "__trap", (u64)&trap },
|
||||||
{ "__trace", (u64)&trace },
|
{ "__trace", (u64)&trace },
|
||||||
{ "__hlecall", (u64)&hack },
|
{ "__hlecall", (u64)&hlecall },
|
||||||
{ "__syscall", (u64)&syscall },
|
{ "__syscall", (u64)&syscall },
|
||||||
{ "__get_tbl", (u64)&tbl },
|
{ "__get_tbl", (u64)&tbl },
|
||||||
{ "__call", (u64)&call },
|
{ "__call", (u64)&call },
|
||||||
|
@ -839,15 +836,11 @@ extern void ppu_initialize(const std::string& name, const std::vector<std::pair<
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
// Initialization
|
||||||
InitializeNativeTarget();
|
InitializeNativeTarget();
|
||||||
InitializeNativeTargetAsmPrinter();
|
InitializeNativeTargetAsmPrinter();
|
||||||
LLVMLinkInMCJIT();
|
LLVMLinkInMCJIT();
|
||||||
|
|
||||||
// Initialization
|
|
||||||
const auto _pi8 = Type::getInt8PtrTy(g_context);
|
|
||||||
const auto _void = Type::getVoidTy(g_context);
|
|
||||||
const auto _func = FunctionType::get(Type::getVoidTy(g_context), false);
|
|
||||||
|
|
||||||
// Create LLVM module
|
// Create LLVM module
|
||||||
std::unique_ptr<Module> module = std::make_unique<Module>(name, g_context);
|
std::unique_ptr<Module> module = std::make_unique<Module>(name, g_context);
|
||||||
|
|
||||||
|
@ -857,6 +850,10 @@ extern void ppu_initialize(const std::string& name, const std::vector<std::pair<
|
||||||
// Initialize translator
|
// Initialize translator
|
||||||
std::unique_ptr<PPUTranslator> translator = std::make_unique<PPUTranslator>(g_context, module.get(), 0, entry);
|
std::unique_ptr<PPUTranslator> translator = std::make_unique<PPUTranslator>(g_context, module.get(), 0, entry);
|
||||||
|
|
||||||
|
// Define some types
|
||||||
|
const auto _void = Type::getVoidTy(g_context);
|
||||||
|
const auto _func = FunctionType::get(_void, { translator->GetContextType()->getPointerTo() }, false);
|
||||||
|
|
||||||
// Initialize function list
|
// Initialize function list
|
||||||
for (const auto& info : funcs)
|
for (const auto& info : funcs)
|
||||||
{
|
{
|
||||||
|
@ -971,7 +968,7 @@ extern void ppu_initialize(const std::string& name, const std::vector<std::pair<
|
||||||
if (info.second)
|
if (info.second)
|
||||||
{
|
{
|
||||||
const std::uintptr_t link = engine->getFunctionAddress(fmt::format("__sub_%x", info.first));
|
const std::uintptr_t link = engine->getFunctionAddress(fmt::format("__sub_%x", info.first));
|
||||||
s_ppu_compiled.emplace(info.first, (void(*)())link);
|
s_ppu_compiled.emplace(info.first, (void(*)(PPUThread&))link);
|
||||||
|
|
||||||
LOG_NOTICE(PPU, "** Function __sub_%x -> 0x%llx (addr=0x%x, size=0x%x)", info.first, link, info.first, info.second);
|
LOG_NOTICE(PPU, "** Function __sub_%x -> 0x%llx (addr=0x%x, size=0x%x)", info.first, link, info.first, info.second);
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,11 @@ PPUTranslator::~PPUTranslator()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Type* PPUTranslator::GetContextType()
|
||||||
|
{
|
||||||
|
return m_thread_type;
|
||||||
|
}
|
||||||
|
|
||||||
void PPUTranslator::AddFunction(u64 addr, Function* func, FunctionType* type)
|
void PPUTranslator::AddFunction(u64 addr, Function* func, FunctionType* type)
|
||||||
{
|
{
|
||||||
if (!m_func_types.emplace(addr, type).second || !m_func_list.emplace(addr, func).second)
|
if (!m_func_types.emplace(addr, type).second || !m_func_list.emplace(addr, func).second)
|
||||||
|
@ -114,7 +119,8 @@ Function* PPUTranslator::TranslateToIR(u64 start_addr, u64 end_addr, be_t<u32>*
|
||||||
m_ir = &builder;
|
m_ir = &builder;
|
||||||
|
|
||||||
/* Create context variables */
|
/* Create context variables */
|
||||||
m_thread = Call(m_thread_type->getPointerTo(), AttributeSet::get(m_context, AttributeSet::FunctionIndex, {Attribute::NoUnwind, Attribute::ReadOnly}), "__context", m_ir->getInt64(start_addr));
|
//m_thread = Call(m_thread_type->getPointerTo(), AttributeSet::get(m_context, AttributeSet::FunctionIndex, {Attribute::NoUnwind, Attribute::ReadOnly}), "__context", m_ir->getInt64(start_addr));
|
||||||
|
m_thread = &*m_function->getArgumentList().begin();
|
||||||
|
|
||||||
// Non-volatile registers with special meaning (TODO)
|
// Non-volatile registers with special meaning (TODO)
|
||||||
m_g_gpr[1] = m_ir->CreateConstGEP2_32(nullptr, m_thread, 0, 1 + 1, ".sp");
|
m_g_gpr[1] = m_ir->CreateConstGEP2_32(nullptr, m_thread, 0, 1 + 1, ".sp");
|
||||||
|
@ -259,7 +265,7 @@ Function* PPUTranslator::TranslateToIR(u64 start_addr, u64 end_addr, be_t<u32>*
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ir->SetInsertPoint(_default);
|
m_ir->SetInsertPoint(_default);
|
||||||
Call(GetType<void>(), "__call", _ctr);
|
Call(GetType<void>(), "__call", m_thread, _ctr);
|
||||||
m_ir->CreateRetVoid();
|
m_ir->CreateRetVoid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,27 +321,13 @@ void PPUTranslator::CallFunction(u64 target, bool tail, Value* indirect)
|
||||||
|
|
||||||
const auto callee_type = func ? m_func_types[target] : nullptr;
|
const auto callee_type = func ? m_func_types[target] : nullptr;
|
||||||
|
|
||||||
// Prepare function arguments
|
const auto result = func ? m_ir->CreateCall(func, {m_thread}) : Call(GetType<void>(), "__call", m_thread, indirect ? indirect : m_ir->getInt64(target));
|
||||||
std::vector<Value*> args;
|
|
||||||
|
|
||||||
if (!callee_type)
|
|
||||||
{
|
|
||||||
// Prepare args for untyped function
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the function
|
|
||||||
const auto result = func ? m_ir->CreateCall(func, args) : Call(GetType<void>(), "__call", indirect ? indirect : m_ir->getInt64(target));
|
|
||||||
|
|
||||||
if (!tail)
|
if (!tail)
|
||||||
{
|
{
|
||||||
UndefineVolatileRegisters();
|
UndefineVolatileRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!callee_type)
|
|
||||||
{
|
|
||||||
// Get result from untyped function
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tail)
|
if (tail)
|
||||||
{
|
{
|
||||||
m_ir->CreateRetVoid();
|
m_ir->CreateRetVoid();
|
||||||
|
@ -1746,13 +1738,13 @@ void PPUTranslator::BC(ppu_opcode_t op)
|
||||||
|
|
||||||
void PPUTranslator::HACK(ppu_opcode_t op)
|
void PPUTranslator::HACK(ppu_opcode_t op)
|
||||||
{
|
{
|
||||||
Call(GetType<void>(), "__hlecall", m_ir->getInt32(op.opcode & 0x3ffffff));
|
Call(GetType<void>(), "__hlecall", m_thread, m_ir->getInt32(op.opcode & 0x3ffffff));
|
||||||
UndefineVolatileRegisters();
|
UndefineVolatileRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPUTranslator::SC(ppu_opcode_t op)
|
void PPUTranslator::SC(ppu_opcode_t op)
|
||||||
{
|
{
|
||||||
Call(GetType<void>(), fmt::format(op.lev == 0 ? "__syscall" : "__lv%ucall", +op.lev), m_ir->CreateLoad(m_gpr[11]));
|
Call(GetType<void>(), fmt::format(op.lev == 0 ? "__syscall" : "__lv%ucall", +op.lev), m_thread, m_ir->CreateLoad(m_gpr[11]));
|
||||||
UndefineVolatileRegisters();
|
UndefineVolatileRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,7 +152,7 @@ class PPUTranslator final //: public CPUTranslator
|
||||||
// Memory base
|
// Memory base
|
||||||
llvm::Value* m_base;
|
llvm::Value* m_base;
|
||||||
|
|
||||||
// Thread context (obtained by __context)
|
// Thread context
|
||||||
llvm::Value* m_thread;
|
llvm::Value* m_thread;
|
||||||
|
|
||||||
// Thread context struct
|
// Thread context struct
|
||||||
|
@ -433,6 +433,9 @@ public:
|
||||||
PPUTranslator(llvm::LLVMContext& context, llvm::Module* module, u64 base, u64 entry);
|
PPUTranslator(llvm::LLVMContext& context, llvm::Module* module, u64 base, u64 entry);
|
||||||
~PPUTranslator();
|
~PPUTranslator();
|
||||||
|
|
||||||
|
// Get thread context struct type
|
||||||
|
llvm::Type* GetContextType();
|
||||||
|
|
||||||
// Add function
|
// Add function
|
||||||
void AddFunction(u64 addr, llvm::Function* func, llvm::FunctionType* type = nullptr);
|
void AddFunction(u64 addr, llvm::Function* func, llvm::FunctionType* type = nullptr);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue