From d177b1adea075123f9f8e8c2d5435689433d3265 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 19 Feb 2015 00:23:31 +0300 Subject: [PATCH] ARMv7: loader fixed --- Utilities/Timer.h | 8 ++-- rpcs3/Emu/ARMv7/ARMv7Decoder.cpp | 15 ++----- rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 27 ++++++++++--- rpcs3/Emu/ARMv7/PSVFuncList.cpp | 59 ++++++++++++++-------------- rpcs3/Emu/ARMv7/PSVFuncList.h | 17 +++++--- rpcs3/Loader/ELF32.cpp | 24 ++++++----- 6 files changed, 85 insertions(+), 65 deletions(-) diff --git a/Utilities/Timer.h b/Utilities/Timer.h index 6be99c9e52..39ccfc0104 100644 --- a/Utilities/Timer.h +++ b/Utilities/Timer.h @@ -28,22 +28,22 @@ public: double GetElapsedTimeInSec() const { - return GetElapsedTimeInMicroSec() / 1000000.0; + return double(GetElapsedTimeInMicroSec()) / 1000000.0; } double GetElapsedTimeInMilliSec() const { - return GetElapsedTimeInMicroSec() / 1000.0; + return double(GetElapsedTimeInMicroSec()) / 1000.0; } - double GetElapsedTimeInMicroSec() const + u64 GetElapsedTimeInMicroSec() const { std::chrono::high_resolution_clock::time_point now = m_stopped ? m_end : std::chrono::high_resolution_clock::now(); return std::chrono::duration_cast(now - m_start).count(); } - double GetElapsedTimeInNanoSec() const + u64 GetElapsedTimeInNanoSec() const { std::chrono::high_resolution_clock::time_point now = m_stopped ? m_end : std::chrono::high_resolution_clock::now(); diff --git a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp index 0b62114b2b..00bffb74c4 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp @@ -1286,17 +1286,10 @@ void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump) // possibly a call to imported function: if (target >= end_addr && ((target - end_addr) % 16) == 0 && (instr & 0xfff000f0) == 0xe0700090) { - // check if implemented - if (const u32 func = (instr & 0xfff00) >> 4 | (instr & 0xf)) - { - // replace BLX with "HACK" instruction directly (in Thumb form), it can help to see where it was called from - vm::psv::write32(addr, 0xf870 | func << 16); - g_opct[0xf8700000 | func] = g_op4t.HACK(); - } - else - { - // leave as is if unimplemented - } + // replace BLX with "HACK" instruction directly (in Thumb form), it can help to see where it was called from + const u32 index = (instr & 0xfff00) >> 4 | (instr & 0xf); + vm::psv::write32(addr, 0xf870 | index << 16); + g_opct[0xf8700000 | index] = g_op4t.HACK(); } else { diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index e07bbaa00b..452da44c12 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -503,20 +503,20 @@ void ARMv7_instrs::UNK(ARMv7Context& context, const ARMv7Code code) void ARMv7_instrs::HACK(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { - u32 cond, func; + u32 cond, index; switch (type) { case T1: { cond = context.ITSTATE.advance(); - func = code.data & 0xffff; + index = code.data & 0xffff; break; } case A1: { cond = code.data >> 28; - func = (code.data & 0xfff00) >> 4 | (code.data & 0xf); + index = (code.data & 0xfff00) >> 4 | (code.data & 0xf); break; } default: throw __FUNCTION__; @@ -524,13 +524,30 @@ void ARMv7_instrs::HACK(ARMv7Context& context, const ARMv7Code code, const ARMv7 if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("hack%s %s", fmt_cond(cond), get_psv_func_by_index(func)->name); + if (context.debug & DF_DISASM) + { + if (auto func = get_psv_func_by_index(index)) + { + if (func->func) + { + context.debug_str = fmt::format("hack%s %s", fmt_cond(cond), func->name); + } + else + { + context.debug_str = fmt::format("hack%s UNIMPLEMENTED:0x%08X (%s)", fmt_cond(cond), func->nid, func->name); + } + } + else + { + context.debug_str = fmt::format("hack%s %d", fmt_cond(cond), index); + } + } if (process_debug(context)) return; } if (ConditionPassed(context, cond)) { - execute_psv_func_by_index(context, func); + execute_psv_func_by_index(context, index); } } diff --git a/rpcs3/Emu/ARMv7/PSVFuncList.cpp b/rpcs3/Emu/ARMv7/PSVFuncList.cpp index 763b36d4af..fdbad45cad 100644 --- a/rpcs3/Emu/ARMv7/PSVFuncList.cpp +++ b/rpcs3/Emu/ARMv7/PSVFuncList.cpp @@ -5,30 +5,50 @@ std::vector g_psv_func_list; std::vector g_psv_modules; -void add_psv_func(psv_func& data) +u32 add_psv_func(psv_func data) { for (auto& f : g_psv_func_list) { - if (f.nid == data.nid && &f - g_psv_func_list.data() >= 2 /* special functions count */) + if (f.nid == data.nid) { + const u32 index = (u32)(&f - g_psv_func_list.data()); + + if (index < SFI_MAX) + { + continue; + } + if (data.func) { f.func = data.func; } - return; + return index; } } g_psv_func_list.push_back(data); + return (u32)(g_psv_func_list.size() - 1); } -const psv_func* get_psv_func_by_nid(u32 nid) +psv_func* get_psv_func_by_nid(u32 nid, u32* out_index) { for (auto& f : g_psv_func_list) { - if (f.nid == nid && &f - g_psv_func_list.data() >= 2 /* special functions count */) + if (f.nid == nid && &f - g_psv_func_list.data()) { + const u32 index = (u32)(&f - g_psv_func_list.data()); + + if (index < SFI_MAX) + { + continue; + } + + if (out_index) + { + *out_index = index; + } + return &f; } } @@ -36,19 +56,7 @@ const psv_func* get_psv_func_by_nid(u32 nid) return nullptr; } -u32 get_psv_func_index(const psv_func* func) -{ - auto res = func - g_psv_func_list.data(); - - if ((size_t)res >= g_psv_func_list.size()) - { - throw __FUNCTION__; - } - - return (u32)res; -} - -const psv_func* get_psv_func_by_index(u32 index) +psv_func* get_psv_func_by_index(u32 index) { if (index >= g_psv_func_list.size()) { @@ -210,24 +218,15 @@ void initialize_psv_modules() g_psv_modules.push_back(&sceXml); // setup special functions (without NIDs) - psv_func unimplemented; - unimplemented.nid = 0; - unimplemented.name = "UNIMPLEMENTED"; - unimplemented.func.reset(new psv_func_detail::func_binder([](ARMv7Context& context) - { - context.thread.m_last_syscall = vm::psv::read32(context.thread.PC + 4); - throw "Unimplemented function"; - })); - g_psv_func_list.push_back(unimplemented); + g_psv_func_list.resize(SFI_MAX); - psv_func hle_return; - hle_return.nid = 1; + psv_func& hle_return = g_psv_func_list[SFI_HLE_RETURN]; + hle_return.nid = 0; hle_return.name = "HLE_RETURN"; hle_return.func.reset(new psv_func_detail::func_binder([](ARMv7Context& context) { context.thread.FastStop(); })); - g_psv_func_list.push_back(hle_return); // load functions for (auto module : g_psv_modules) diff --git a/rpcs3/Emu/ARMv7/PSVFuncList.h b/rpcs3/Emu/ARMv7/PSVFuncList.h index 34cd990c93..ed2d9217a8 100644 --- a/rpcs3/Emu/ARMv7/PSVFuncList.h +++ b/rpcs3/Emu/ARMv7/PSVFuncList.h @@ -478,8 +478,15 @@ struct psv_func psv_log_base* module; // Module for information }; +enum psv_special_function_index : u16 +{ + SFI_HLE_RETURN, + + SFI_MAX +}; + // Do not call directly -void add_psv_func(psv_func& data); +u32 add_psv_func(psv_func data); // Do not call directly template void reg_psv_func(u32 nid, psv_log_base* module, const char* name, RT(*func)(T...)) { @@ -491,12 +498,10 @@ template void reg_psv_func(u32 nid, psv_log_base* mo add_psv_func(f); } -// Find registered HLE function by its ID -const psv_func* get_psv_func_by_nid(u32 nid); -// Get index of registered HLE function -u32 get_psv_func_index(const psv_func* func); +// Find registered HLE function by NID +psv_func* get_psv_func_by_nid(u32 nid, u32* out_index = nullptr); // Find registered HLE function by its index -const psv_func* get_psv_func_by_index(u32 index); +psv_func* get_psv_func_by_index(u32 index); // Execute registered HLE function by its index void execute_psv_func_by_index(ARMv7Context& context, u32 index); // Register all HLE functions diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index a118451126..42de280949 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -134,7 +134,7 @@ namespace loader auto armv7_thr_stop_data = vm::psv::ptr::make(Memory.PSV.RAM.AllocAlign(3 * 4)); armv7_thr_stop_data[0] = 0xf870; // HACK instruction (Thumb) - armv7_thr_stop_data[1] = 0x0001; // index 1 + armv7_thr_stop_data[1] = SFI_HLE_RETURN; Emu.SetCPUThreadStop(armv7_thr_stop_data.addr()); u32 entry = 0; // actual entry point (ELFs entry point is ignored) @@ -228,28 +228,34 @@ namespace loader const u32 nid = fnid[j]; const u32 addr = fstub[j]; - if (auto func = get_psv_func_by_nid(nid)) + u32 index; + + if (auto func = get_psv_func_by_nid(nid, &index)) { if (func->module) { - func->module->Notice("Imported function %s (nid=0x%08x, addr=0x%x)", func->name, nid, addr); + LOG_NOTICE(LOADER, "Imported function '%s' in module '%s' (nid=0x%08x, addr=0x%x)", func->name, func->module->GetName(), nid, addr); } else { - LOG_NOTICE(LOADER, "Imported function %s (nid=0x%08x, addr=0x%x)", func->name, nid, addr); + LOG_NOTICE(LOADER, "Imported function '%s' (nid=0x%08x, addr=0x%x)", func->name, nid, addr); } - - const u32 code = get_psv_func_index(func); - vm::psv::write32(addr + 0, 0xe0700090 | (code & 0xfff0) << 4 | (code & 0xf)); // HACK instruction (ARM) } else { LOG_ERROR(LOADER, "Unknown function 0x%08x (addr=0x%x)", nid, addr); - vm::psv::write32(addr + 0, 0xe0700090); // HACK instruction (ARM), unimplemented stub (code 0) - vm::psv::write32(addr + 4, nid); // nid + psv_func unimplemented; + unimplemented.nid = nid; + unimplemented.module = nullptr; + unimplemented.name = "UNKNOWN"; // TODO: set correct name if possible + unimplemented.func = nullptr; + + index = add_psv_func(unimplemented); } + vm::psv::write32(addr + 0, 0xe0700090 | (index & 0xfff0) << 4 | (index & 0xf)); // HACK instruction (ARM) + code_end = std::min(addr, code_end); } }