mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-07 15:31:26 +12:00
PPUThread refactoring
`CallbackManager` removed, added _gcm_intr_thread for cellGcmSys `PPUThread` renamed to `ppu_thread`, inheritance allowed Added lightweight command queue for `ppu_thread` Implemented call stack dump for PPU `get_current_thread_mutex` removed `thread_ctrl::spawn`: minor initialization fix `thread_ctrl::wait_for` added `named_thread`: some methods added `cpu_thread::run` added Some bugs fixes, including SPU channels
This commit is contained in:
parent
33c59fa51b
commit
f8719c1230
99 changed files with 4480 additions and 4592 deletions
|
@ -114,9 +114,9 @@ cfg::set_entry g_cfg_load_libs(cfg::root.core, "Load libraries");
|
|||
extern std::string ppu_get_function_name(const std::string& module, u32 fnid);
|
||||
extern std::string ppu_get_variable_name(const std::string& module, u32 vnid);
|
||||
|
||||
extern void sys_initialize_tls(PPUThread&, u64, u32, u32, u32);
|
||||
extern void sys_initialize_tls(ppu_thread&, u64, u32, u32, u32);
|
||||
|
||||
extern void ppu_initialize(const std::string& name, const std::vector<ppu_function>& set, u32 entry);
|
||||
extern void ppu_initialize(const std::string& name, const std::vector<ppu_function>& set);
|
||||
|
||||
extern u32 g_ps3_sdk_version;
|
||||
|
||||
|
@ -139,17 +139,17 @@ extern std::string ppu_get_module_function_name(u32 index)
|
|||
return fmt::format(".%u", index);
|
||||
}
|
||||
|
||||
extern void ppu_execute_function(PPUThread& ppu, u32 index)
|
||||
extern void ppu_execute_function(ppu_thread& ppu, u32 index)
|
||||
{
|
||||
if (index < g_ppu_function_cache.size())
|
||||
{
|
||||
// If autopause occures, check_status() will hold the thread until unpaused.
|
||||
if (debug::autopause::pause_function(g_ppu_fnid_cache[index]) && ppu.check_status()) throw cpu_state::ret;
|
||||
if (debug::autopause::pause_function(g_ppu_fnid_cache[index]) && ppu.check_state()) throw cpu_state::ret;
|
||||
|
||||
if (const auto func = g_ppu_function_cache[index])
|
||||
{
|
||||
func(ppu);
|
||||
LOG_TRACE(HLE, "'%s' finished, r3=0x%llx", ppu_get_module_function_name(index), ppu.GPR[3]);
|
||||
LOG_TRACE(HLE, "'%s' finished, r3=0x%llx", ppu_get_module_function_name(index), ppu.gpr[3]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -783,7 +783,7 @@ std::shared_ptr<lv2_prx_t> ppu_load_prx(const ppu_prx_object& elf)
|
|||
const u32 addr = vm::cast(s.sh_addr);
|
||||
const u32 size = vm::cast(s.sh_size);
|
||||
|
||||
if (s.sh_type == 1 && addr && size)
|
||||
if (s.sh_type == 1 && addr && size) // TODO: some sections with addr=0 are valid
|
||||
{
|
||||
for (auto i = 0; i < segments.size(); i++)
|
||||
{
|
||||
|
@ -1138,7 +1138,15 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
|||
// Add functions
|
||||
exec_set.insert(exec_set.end(), prx->funcs.begin(), prx->funcs.end());
|
||||
|
||||
ppu_validate(lle_dir + '/' + name, prx->funcs, prx->funcs[0].addr);
|
||||
if (prx->funcs.empty())
|
||||
{
|
||||
LOG_FATAL(LOADER, "Module %s has no functions!", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: fix arguments
|
||||
ppu_validate(lle_dir + '/' + name, prx->funcs, prx->funcs[0].addr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1279,100 +1287,19 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
|||
exec_set.emplace_back(pair);
|
||||
}
|
||||
|
||||
// TODO: adjust for liblv2 loading option
|
||||
using namespace ppu_instructions;
|
||||
|
||||
static const int branch_size = 10 * 4;
|
||||
|
||||
auto make_branch = [](vm::ptr<u32>& ptr, u32 addr, bool last)
|
||||
{
|
||||
const u32 stub = vm::read32(addr);
|
||||
const u32 rtoc = vm::read32(addr + 4);
|
||||
|
||||
*ptr++ = LI(r0, 0);
|
||||
*ptr++ = ORI(r0, r0, stub & 0xffff);
|
||||
*ptr++ = ORIS(r0, r0, stub >> 16);
|
||||
*ptr++ = LI(r2, 0);
|
||||
*ptr++ = ORI(r2, r2, rtoc & 0xffff);
|
||||
*ptr++ = ORIS(r2, r2, rtoc >> 16);
|
||||
*ptr++ = MTCTR(r0);
|
||||
*ptr++ = last ? BCTR() : BCTRL();
|
||||
};
|
||||
|
||||
auto entry = vm::ptr<u32>::make(vm::alloc(48 + branch_size * (::size32(start_funcs) + 1), vm::main));
|
||||
|
||||
// Save initialization args
|
||||
*entry++ = MR(r14, r3);
|
||||
*entry++ = MR(r15, r4);
|
||||
*entry++ = MR(r16, r5);
|
||||
*entry++ = MR(r17, r6);
|
||||
*entry++ = MR(r18, r11);
|
||||
*entry++ = MR(r19, r12);
|
||||
|
||||
if (!g_cfg_load_liblv2)
|
||||
{
|
||||
// Call sys_initialize_tls explicitly
|
||||
*entry++ = MR(r3, r7);
|
||||
*entry++ = MR(r4, r8);
|
||||
*entry++ = MR(r5, r9);
|
||||
*entry++ = MR(r6, r10);
|
||||
*entry++ = HACK(FIND_FUNC(sys_initialize_tls));
|
||||
}
|
||||
|
||||
for (auto& f : start_funcs)
|
||||
{
|
||||
// Reset arguments (TODO)
|
||||
*entry++ = LI(r3, 0);
|
||||
*entry++ = LI(r4, 0);
|
||||
make_branch(entry, f, false);
|
||||
}
|
||||
|
||||
// Restore initialization args
|
||||
*entry++ = MR(r3, r14);
|
||||
*entry++ = MR(r4, r15);
|
||||
*entry++ = MR(r5, r16);
|
||||
*entry++ = MR(r6, r17);
|
||||
*entry++ = MR(r11, r18);
|
||||
*entry++ = MR(r12, r19);
|
||||
|
||||
// Branch to initialization
|
||||
make_branch(entry, static_cast<u32>(elf.header.e_entry), false);
|
||||
|
||||
// Register entry function (addr, size)
|
||||
ppu_function entry_func;
|
||||
entry_func.addr = entry.addr() & -0x1000;
|
||||
entry_func.size = entry.addr() & 0xfff;
|
||||
entry_func.attr += ppu_attr::entry_point;
|
||||
exec_set.emplace_back(entry_func);
|
||||
|
||||
// Initialize recompiler
|
||||
ppu_initialize("", exec_set, static_cast<u32>(elf.header.e_entry));
|
||||
// Initialize interpreter/recompiler
|
||||
ppu_initialize("", exec_set);
|
||||
|
||||
// Set SDK version
|
||||
g_ps3_sdk_version = sdk_version;
|
||||
|
||||
auto ppu = idm::make_ptr<PPUThread>("main_thread");
|
||||
|
||||
ppu->pc = entry.addr() & -0x1000;
|
||||
ppu->stack_size = std::max<u32>(primary_stacksize, 0x4000);
|
||||
ppu->prio = primary_prio;
|
||||
ppu->cpu_init();
|
||||
|
||||
ppu->GPR[2] = 0xdeadbeef; // rtoc
|
||||
ppu->GPR[11] = 0xabadcafe; // OPD ???
|
||||
ppu->GPR[12] = malloc_pagesize;
|
||||
|
||||
// Initialize process arguments
|
||||
std::initializer_list<std::string> args = { Emu.GetPath()/*, "-emu"s*/ };
|
||||
|
||||
auto argv = vm::ptr<u64>::make(vm::alloc(SIZE_32(u64) * ::size32(args), vm::main));
|
||||
auto envp = vm::ptr<u64>::make(vm::alloc(::align(SIZE_32(u64), 0x10), vm::main));
|
||||
*envp = 0;
|
||||
|
||||
ppu->GPR[3] = args.size(); // argc
|
||||
ppu->GPR[4] = argv.addr();
|
||||
ppu->GPR[5] = envp.addr();
|
||||
ppu->GPR[6] = 0; // ???
|
||||
|
||||
for (const auto& arg : args)
|
||||
{
|
||||
const u32 arg_size = ::align(::size32(arg) + 1, 0x10);
|
||||
|
@ -1383,15 +1310,43 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
|||
*argv++ = arg_addr;
|
||||
}
|
||||
|
||||
// Arguments for sys_initialize_tls()
|
||||
ppu->GPR[7] = ppu->id;
|
||||
ppu->GPR[8] = tls_vaddr;
|
||||
ppu->GPR[9] = tls_fsize;
|
||||
ppu->GPR[10] = tls_vsize;
|
||||
argv -= args.size();
|
||||
|
||||
//ppu->state += cpu_state::interrupt;
|
||||
// Initialize main thread
|
||||
auto ppu = idm::make_ptr<ppu_thread>("main_thread", primary_prio, primary_stacksize);
|
||||
|
||||
// Set memory protection
|
||||
// TODO: adjust for liblv2 loading option
|
||||
if (!g_cfg_load_liblv2)
|
||||
{
|
||||
// Set TLS args, call sys_initialize_tls
|
||||
ppu->cmd_list
|
||||
({
|
||||
{ ppu_cmd::set_args, 4 }, u64{ppu->id}, u64{tls_vaddr}, u64{tls_fsize}, u64{tls_vsize},
|
||||
{ ppu_cmd::hle_call, FIND_FUNC(sys_initialize_tls) },
|
||||
});
|
||||
}
|
||||
|
||||
// Run start functions
|
||||
for (u32 func : start_funcs)
|
||||
{
|
||||
// Reset arguments, run module entry point function
|
||||
ppu->cmd_list
|
||||
({
|
||||
{ ppu_cmd::set_args, 2 }, u64{0}, u64{0},
|
||||
{ ppu_cmd::lle_call, func },
|
||||
});
|
||||
}
|
||||
|
||||
// Set command line arguments, run entry function
|
||||
ppu->cmd_list
|
||||
({
|
||||
{ ppu_cmd::set_args, 8 }, u64{args.size()}, u64{argv.addr()}, u64{envp.addr()}, u64{0}, u64{ppu->id}, u64{tls_vaddr}, u64{tls_fsize}, u64{tls_vsize},
|
||||
{ ppu_cmd::set_gpr, 11 }, u64{0xabadcafe},
|
||||
{ ppu_cmd::set_gpr, 12 }, u64{malloc_pagesize},
|
||||
{ ppu_cmd::lle_call, static_cast<u32>(elf.header.e_entry) },
|
||||
});
|
||||
|
||||
// Set actual memory protection (experimental)
|
||||
for (const auto& prog : elf.progs)
|
||||
{
|
||||
const u32 addr = static_cast<u32>(prog.p_vaddr);
|
||||
|
@ -1399,7 +1354,7 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
|||
|
||||
if (prog.p_type == 0x1 /* LOAD */ && prog.p_memsz && (prog.p_flags & 0x2) == 0 /* W */)
|
||||
{
|
||||
// Set memory protection to read-only where necessary
|
||||
// Set memory protection to read-only when necessary
|
||||
VERIFY(vm::page_protect(addr, ::align(size, 0x1000), 0, 0, vm::page_writable));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue