mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 02:32:36 +01:00
ARMv7: loader fixed
This commit is contained in:
parent
1003c42310
commit
d177b1adea
@ -28,22 +28,22 @@ public:
|
|||||||
|
|
||||||
double GetElapsedTimeInSec() const
|
double GetElapsedTimeInSec() const
|
||||||
{
|
{
|
||||||
return GetElapsedTimeInMicroSec() / 1000000.0;
|
return double(GetElapsedTimeInMicroSec()) / 1000000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double GetElapsedTimeInMilliSec() const
|
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();
|
std::chrono::high_resolution_clock::time_point now = m_stopped ? m_end : std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
return std::chrono::duration_cast<std::chrono::microseconds>(now - m_start).count();
|
return std::chrono::duration_cast<std::chrono::microseconds>(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();
|
std::chrono::high_resolution_clock::time_point now = m_stopped ? m_end : std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
@ -1286,17 +1286,10 @@ void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump)
|
|||||||
// possibly a call to imported function:
|
// possibly a call to imported function:
|
||||||
if (target >= end_addr && ((target - end_addr) % 16) == 0 && (instr & 0xfff000f0) == 0xe0700090)
|
if (target >= end_addr && ((target - end_addr) % 16) == 0 && (instr & 0xfff000f0) == 0xe0700090)
|
||||||
{
|
{
|
||||||
// check if implemented
|
// replace BLX with "HACK" instruction directly (in Thumb form), it can help to see where it was called from
|
||||||
if (const u32 func = (instr & 0xfff00) >> 4 | (instr & 0xf))
|
const u32 index = (instr & 0xfff00) >> 4 | (instr & 0xf);
|
||||||
{
|
vm::psv::write32(addr, 0xf870 | index << 16);
|
||||||
// replace BLX with "HACK" instruction directly (in Thumb form), it can help to see where it was called from
|
g_opct[0xf8700000 | index] = g_op4t.HACK();
|
||||||
vm::psv::write32(addr, 0xf870 | func << 16);
|
|
||||||
g_opct[0xf8700000 | func] = g_op4t.HACK();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// leave as is if unimplemented
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -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)
|
void ARMv7_instrs::HACK(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
|
||||||
{
|
{
|
||||||
u32 cond, func;
|
u32 cond, index;
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case T1:
|
case T1:
|
||||||
{
|
{
|
||||||
cond = context.ITSTATE.advance();
|
cond = context.ITSTATE.advance();
|
||||||
func = code.data & 0xffff;
|
index = code.data & 0xffff;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case A1:
|
case A1:
|
||||||
{
|
{
|
||||||
cond = code.data >> 28;
|
cond = code.data >> 28;
|
||||||
func = (code.data & 0xfff00) >> 4 | (code.data & 0xf);
|
index = (code.data & 0xfff00) >> 4 | (code.data & 0xf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: throw __FUNCTION__;
|
default: throw __FUNCTION__;
|
||||||
@ -524,13 +524,30 @@ void ARMv7_instrs::HACK(ARMv7Context& context, const ARMv7Code code, const ARMv7
|
|||||||
|
|
||||||
if (context.debug)
|
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 (process_debug(context)) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ConditionPassed(context, cond))
|
if (ConditionPassed(context, cond))
|
||||||
{
|
{
|
||||||
execute_psv_func_by_index(context, func);
|
execute_psv_func_by_index(context, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,30 +5,50 @@
|
|||||||
std::vector<psv_func> g_psv_func_list;
|
std::vector<psv_func> g_psv_func_list;
|
||||||
std::vector<psv_log_base*> g_psv_modules;
|
std::vector<psv_log_base*> g_psv_modules;
|
||||||
|
|
||||||
void add_psv_func(psv_func& data)
|
u32 add_psv_func(psv_func data)
|
||||||
{
|
{
|
||||||
for (auto& f : g_psv_func_list)
|
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)
|
if (data.func)
|
||||||
{
|
{
|
||||||
f.func = data.func;
|
f.func = data.func;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_psv_func_list.push_back(data);
|
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)
|
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;
|
return &f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -36,19 +56,7 @@ const psv_func* get_psv_func_by_nid(u32 nid)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 get_psv_func_index(const psv_func* func)
|
psv_func* get_psv_func_by_index(u32 index)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
if (index >= g_psv_func_list.size())
|
if (index >= g_psv_func_list.size())
|
||||||
{
|
{
|
||||||
@ -210,24 +218,15 @@ void initialize_psv_modules()
|
|||||||
g_psv_modules.push_back(&sceXml);
|
g_psv_modules.push_back(&sceXml);
|
||||||
|
|
||||||
// setup special functions (without NIDs)
|
// setup special functions (without NIDs)
|
||||||
psv_func unimplemented;
|
g_psv_func_list.resize(SFI_MAX);
|
||||||
unimplemented.nid = 0;
|
|
||||||
unimplemented.name = "UNIMPLEMENTED";
|
|
||||||
unimplemented.func.reset(new psv_func_detail::func_binder<void, ARMv7Context&>([](ARMv7Context& context)
|
|
||||||
{
|
|
||||||
context.thread.m_last_syscall = vm::psv::read32(context.thread.PC + 4);
|
|
||||||
throw "Unimplemented function";
|
|
||||||
}));
|
|
||||||
g_psv_func_list.push_back(unimplemented);
|
|
||||||
|
|
||||||
psv_func hle_return;
|
psv_func& hle_return = g_psv_func_list[SFI_HLE_RETURN];
|
||||||
hle_return.nid = 1;
|
hle_return.nid = 0;
|
||||||
hle_return.name = "HLE_RETURN";
|
hle_return.name = "HLE_RETURN";
|
||||||
hle_return.func.reset(new psv_func_detail::func_binder<void, ARMv7Context&>([](ARMv7Context& context)
|
hle_return.func.reset(new psv_func_detail::func_binder<void, ARMv7Context&>([](ARMv7Context& context)
|
||||||
{
|
{
|
||||||
context.thread.FastStop();
|
context.thread.FastStop();
|
||||||
}));
|
}));
|
||||||
g_psv_func_list.push_back(hle_return);
|
|
||||||
|
|
||||||
// load functions
|
// load functions
|
||||||
for (auto module : g_psv_modules)
|
for (auto module : g_psv_modules)
|
||||||
|
@ -478,8 +478,15 @@ struct psv_func
|
|||||||
psv_log_base* module; // Module for information
|
psv_log_base* module; // Module for information
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum psv_special_function_index : u16
|
||||||
|
{
|
||||||
|
SFI_HLE_RETURN,
|
||||||
|
|
||||||
|
SFI_MAX
|
||||||
|
};
|
||||||
|
|
||||||
// Do not call directly
|
// Do not call directly
|
||||||
void add_psv_func(psv_func& data);
|
u32 add_psv_func(psv_func data);
|
||||||
// Do not call directly
|
// Do not call directly
|
||||||
template<typename RT, typename... T> void reg_psv_func(u32 nid, psv_log_base* module, const char* name, RT(*func)(T...))
|
template<typename RT, typename... T> void reg_psv_func(u32 nid, psv_log_base* module, const char* name, RT(*func)(T...))
|
||||||
{
|
{
|
||||||
@ -491,12 +498,10 @@ template<typename RT, typename... T> void reg_psv_func(u32 nid, psv_log_base* mo
|
|||||||
|
|
||||||
add_psv_func(f);
|
add_psv_func(f);
|
||||||
}
|
}
|
||||||
// Find registered HLE function by its ID
|
// Find registered HLE function by NID
|
||||||
const psv_func* get_psv_func_by_nid(u32 nid);
|
psv_func* get_psv_func_by_nid(u32 nid, u32* out_index = nullptr);
|
||||||
// Get index of registered HLE function
|
|
||||||
u32 get_psv_func_index(const psv_func* func);
|
|
||||||
// Find registered HLE function by its index
|
// 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
|
// Execute registered HLE function by its index
|
||||||
void execute_psv_func_by_index(ARMv7Context& context, u32 index);
|
void execute_psv_func_by_index(ARMv7Context& context, u32 index);
|
||||||
// Register all HLE functions
|
// Register all HLE functions
|
||||||
|
@ -134,7 +134,7 @@ namespace loader
|
|||||||
|
|
||||||
auto armv7_thr_stop_data = vm::psv::ptr<u32>::make(Memory.PSV.RAM.AllocAlign(3 * 4));
|
auto armv7_thr_stop_data = vm::psv::ptr<u32>::make(Memory.PSV.RAM.AllocAlign(3 * 4));
|
||||||
armv7_thr_stop_data[0] = 0xf870; // HACK instruction (Thumb)
|
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());
|
Emu.SetCPUThreadStop(armv7_thr_stop_data.addr());
|
||||||
|
|
||||||
u32 entry = 0; // actual entry point (ELFs entry point is ignored)
|
u32 entry = 0; // actual entry point (ELFs entry point is ignored)
|
||||||
@ -228,28 +228,34 @@ namespace loader
|
|||||||
const u32 nid = fnid[j];
|
const u32 nid = fnid[j];
|
||||||
const u32 addr = fstub[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)
|
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
|
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
|
else
|
||||||
{
|
{
|
||||||
LOG_ERROR(LOADER, "Unknown function 0x%08x (addr=0x%x)", nid, addr);
|
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)
|
psv_func unimplemented;
|
||||||
vm::psv::write32(addr + 4, nid); // nid
|
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<u32>(addr, code_end);
|
code_end = std::min<u32>(addr, code_end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user