diff --git a/rpcs3/Emu/Cell/Modules/StaticHLE.cpp b/rpcs3/Emu/Cell/Modules/StaticHLE.cpp index 8a6df2bb77..decf537359 100644 --- a/rpcs3/Emu/Cell/Modules/StaticHLE.cpp +++ b/rpcs3/Emu/Cell/Modules/StaticHLE.cpp @@ -164,7 +164,7 @@ bool statichle_handler::check_against_patterns(vm::cptr& data, u32 size, u32 } const auto sfunc = &smodule->functions.at(pat.fnid); - const u32 target = ppu_function_manager::addr + 8 * sfunc->index; + const u32 target = ppu_function_manager::func_addr(sfunc->index) + 4; // write stub vm::write32(addr, ppu_instructions::LIS(0, (target&0xFFFF0000)>>16)); diff --git a/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp b/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp index 249a582cb3..5bf2d3ddd6 100644 --- a/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp @@ -417,7 +417,7 @@ error_code _cellGcmInitBody(ppu_thread& ppu, vm::pptr contex gcm_cfg->current_context.begin.set(g_defaultCommandBufferBegin + 4096); // 4 kb reserved at the beginning gcm_cfg->current_context.end.set(g_defaultCommandBufferBegin + 32 * 1024 - 4); // 4b at the end for jump gcm_cfg->current_context.current = gcm_cfg->current_context.begin; - gcm_cfg->current_context.callback.set(ppu_function_manager::addr + 8 * FIND_FUNC(cellGcmCallback)); + gcm_cfg->current_context.callback.set(ppu_function_manager::func_addr(FIND_FUNC(cellGcmCallback))); gcm_cfg->ctxt_addr = context.addr(); gcm_cfg->gcm_buffers.set(vm::alloc(sizeof(CellGcmDisplayInfo) * 8, vm::main)); diff --git a/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp b/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp index da750fb59d..127f9f5060 100644 --- a/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp +++ b/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp @@ -255,7 +255,7 @@ error_code open_exit_dialog(const std::string& message, bool is_exit_requested) if (is_exit_requested) { - callback.set(ppu_function_manager::addr + 8 * FIND_FUNC(exit_game)); + callback.set(ppu_function_manager::func_addr(FIND_FUNC(exit_game))); } const error_code res = open_msg_dialog diff --git a/rpcs3/Emu/Cell/PPUDisAsm.cpp b/rpcs3/Emu/Cell/PPUDisAsm.cpp index 79a33873c3..2b82fa73ef 100644 --- a/rpcs3/Emu/Cell/PPUDisAsm.cpp +++ b/rpcs3/Emu/Cell/PPUDisAsm.cpp @@ -2346,12 +2346,12 @@ extern std::vector g_ppu_function_names; void PPUDisAsm::UNK(ppu_opcode_t op) { - if (op.opcode == dump_pc && ppu_function_manager::addr) + if (ppu_function_manager::addr) { // HLE function index const u32 index = (dump_pc - ppu_function_manager::addr) / 8; - if (index < ppu_function_manager::get().size()) + if (dump_pc % 8 == 4 && index < ppu_function_manager::get().size()) { Write(fmt::format("Function : %s (index %u)", index < g_ppu_function_names.size() ? g_ppu_function_names[index].c_str() : "?", index)); return; diff --git a/rpcs3/Emu/Cell/PPUFunction.h b/rpcs3/Emu/Cell/PPUFunction.h index b9d1afcd2f..cd6c68333b 100644 --- a/rpcs3/Emu/Cell/PPUFunction.h +++ b/rpcs3/Emu/Cell/PPUFunction.h @@ -281,6 +281,16 @@ public: return access(); } + static inline u32 func_addr(u32 index) + { + if (index >= access().size() || !addr) + { + return 0; + } + + return addr + index * 8; + } + // Allocation address static u32 addr; }; diff --git a/rpcs3/Emu/Cell/PPUInterpreter.cpp b/rpcs3/Emu/Cell/PPUInterpreter.cpp index 41343c439d..b40487cf74 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.cpp +++ b/rpcs3/Emu/Cell/PPUInterpreter.cpp @@ -6,6 +6,7 @@ #include "PPUThread.h" #include "Utilities/sysinfo.h" #include "Emu/Cell/Common.h" +#include "Emu/Cell/PPUFunction.h" #include #include @@ -5173,5 +5174,15 @@ bool ppu_interpreter::FCFID(ppu_thread& ppu, ppu_opcode_t op) bool ppu_interpreter::UNK(ppu_thread& ppu, ppu_opcode_t op) { + // HLE function index + const u32 index = (ppu.cia - ppu_function_manager::addr) / 8; + + const auto& hle_funcs = ppu_function_manager::get(); + + if (ppu.cia % 8 == 4 && index < hle_funcs.size()) + { + return hle_funcs[index](ppu); + } + fmt::throw_exception("Unknown/Illegal opcode: 0x%08x at 0x%x", op.opcode, ppu.cia); } diff --git a/rpcs3/Emu/Cell/PPUModule.cpp b/rpcs3/Emu/Cell/PPUModule.cpp index 50e22cf8bf..82a159684d 100644 --- a/rpcs3/Emu/Cell/PPUModule.cpp +++ b/rpcs3/Emu/Cell/PPUModule.cpp @@ -253,13 +253,13 @@ static void ppu_initialize_modules(ppu_linkage_info* link) // Fill the array (visible data: self address and function index) for (u32 addr = ppu_function_manager::addr, index = 0; index < hle_funcs.size(); addr += 8, index++) { - // Function address = current address, RTOC = BLR instruction for the interpreter - vm::write32(addr + 0, addr); - vm::write32(addr + 4, ppu_instructions::BLR()); + // Function address = next CIA, RTOC = 0 (vm::null) + vm::write32(addr + 0, addr + 4); + vm::write32(addr + 4, 0); // Register the HLE function directly - ppu_register_function_at(addr + 0, 4, hle_funcs[index]); - ppu_register_function_at(addr + 4, 4, nullptr); + ppu_register_function_at(addr + 0, 4, nullptr); + ppu_register_function_at(addr + 4, 4, hle_funcs[index]); } // Set memory protection to read-only @@ -303,7 +303,7 @@ static void ppu_initialize_modules(ppu_linkage_info* link) auto& flink = linkage.functions[function.first]; flink.static_func = &function.second; - flink.export_addr = ppu_function_manager::addr + 8 * function.second.index; + flink.export_addr = ppu_function_manager::func_addr(function.second.index); function.second.export_addr = &flink.export_addr; } } @@ -507,7 +507,7 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo // Function linkage info auto& flink = mlink.functions[fnid]; - if (flink.static_func && flink.export_addr == ppu_function_manager::addr + 8 * flink.static_func->index) + if (flink.static_func && flink.export_addr == ppu_function_manager::func_addr(flink.static_func->index)) { flink.export_addr = 0; } @@ -525,10 +525,10 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo { // Inject a branch to the HLE implementation const u32 _entry = vm::read32(faddr); - const u32 target = ppu_function_manager::addr + 8 * _sf->index; + const u32 target = ppu_function_manager::func_addr(_sf->index) + 4; // Set exported function - flink.export_addr = target; + flink.export_addr = target - 4; if ((target <= _entry && _entry - target <= 0x2000000) || (target > _entry && target - _entry < 0x2000000)) { @@ -1107,7 +1107,7 @@ void ppu_unload_prx(const lv2_prx& prx) // auto pinfo = static_cast(exp.second); // if (pinfo->static_func) // { - // pinfo->export_addr = ppu_function_manager::addr + 8 * pinfo->static_func->index; + // pinfo->export_addr = ppu_function_manager::func_addr(pinfo->static_func->index); // } // else if (pinfo->static_var) // { diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index fae3aeca38..28093be909 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -183,21 +183,11 @@ void ppu_reservation_fallback(ppu_thread& ppu) { const auto& table = g_ppu_interpreter_fast.get_table(); - const u32 min_hle = ppu_function_manager::addr ? ppu_function_manager::addr : UINT32_MAX; - const u32 max_hle = min_hle + ppu_function_manager::get().size() * 8 - 1; - while (true) { // Run instructions in interpreter const u32 op = vm::read32(ppu.cia); - if (op == ppu.cia && ppu.cia >= min_hle && ppu.cia <= max_hle) - { - // HLE function - // ppu.raddr = 0; - return; - } - if (table[ppu_decode(op)](ppu, {op})) [[likely]] { ppu.cia += 4; @@ -643,7 +633,7 @@ std::vector> ppu_thread::dump_callstack_list() const } // Ignore HLE stop address - return addr == ppu_function_manager::addr + 8; + return addr == ppu_function_manager::func_addr(1) + 4; }; if (is_invalid(addr)) @@ -1039,7 +1029,7 @@ void ppu_thread::fast_call(u32 addr, u32 rtoc) cia = addr; gpr[2] = rtoc; - lr = ppu_function_manager::addr + 8; // HLE stop address + lr = ppu_function_manager::func_addr(1) + 4; // HLE stop address current_function = nullptr; g_tls_log_prefix = []