mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-23 03:02:53 +01:00
ARMv7: bugfix, loader improved, scePerf
This commit is contained in:
parent
e5dd03dbcb
commit
dab80497bb
@ -119,6 +119,14 @@ struct ARMv7Context
|
||||
u32 R_ADDR;
|
||||
u64 R_DATA;
|
||||
|
||||
struct perf_counter
|
||||
{
|
||||
u32 event;
|
||||
u32 value;
|
||||
};
|
||||
|
||||
std::array<perf_counter, 6> counters;
|
||||
|
||||
void write_gpr(u32 n, u32 value)
|
||||
{
|
||||
assert(n < 16);
|
||||
|
@ -116,6 +116,7 @@ void ARMv7Thread::InitRegs()
|
||||
context.ITSTATE.IT = 0;
|
||||
context.SP = m_stack_addr + m_stack_size;
|
||||
context.TLS = armv7_get_tls(GetId());
|
||||
context.R_ADDR = 0;
|
||||
}
|
||||
|
||||
void ARMv7Thread::InitStack()
|
||||
|
@ -42,7 +42,7 @@ s32 sceKernelCreateThread(
|
||||
s32 cpuAffinityMask,
|
||||
vm::psv::ptr<const SceKernelThreadOptParam> pOptParam)
|
||||
{
|
||||
sceLibKernel.Error("sceKernelCreateThread(pName=0x%x, entry=0x%x, initPriority=%d, stackSize=0x%x, attr=0x%x, cpuAffinityMask=0x%x, pOptParam=0x%x)",
|
||||
sceLibKernel.Warning("sceKernelCreateThread(pName=0x%x, entry=0x%x, initPriority=%d, stackSize=0x%x, attr=0x%x, cpuAffinityMask=0x%x, pOptParam=0x%x)",
|
||||
pName, entry, initPriority, stackSize, attr, cpuAffinityMask, pOptParam);
|
||||
|
||||
ARMv7Thread& new_thread = static_cast<ARMv7Thread&>(Emu.GetCPU().AddThread(CPU_THREAD_ARMv7));
|
||||
@ -61,7 +61,7 @@ s32 sceKernelCreateThread(
|
||||
|
||||
s32 sceKernelStartThread(s32 threadId, u32 argSize, vm::psv::ptr<const void> pArgBlock)
|
||||
{
|
||||
sceLibKernel.Error("sceKernelStartThread(threadId=0x%x, argSize=0x%x, pArgBlock=0x%x)", threadId, argSize, pArgBlock);
|
||||
sceLibKernel.Warning("sceKernelStartThread(threadId=0x%x, argSize=0x%x, pArgBlock=0x%x)", threadId, argSize, pArgBlock);
|
||||
|
||||
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(threadId, CPU_THREAD_ARMv7);
|
||||
|
||||
@ -93,7 +93,7 @@ s32 sceKernelStartThread(s32 threadId, u32 argSize, vm::psv::ptr<const void> pAr
|
||||
|
||||
s32 sceKernelExitThread(ARMv7Context& context, s32 exitStatus)
|
||||
{
|
||||
sceLibKernel.Error("sceKernelExitThread(exitStatus=0x%x)", exitStatus);
|
||||
sceLibKernel.Warning("sceKernelExitThread(exitStatus=0x%x)", exitStatus);
|
||||
|
||||
// exit status is stored in r0
|
||||
context.thread.Stop();
|
||||
@ -103,7 +103,7 @@ s32 sceKernelExitThread(ARMv7Context& context, s32 exitStatus)
|
||||
|
||||
s32 sceKernelDeleteThread(s32 threadId)
|
||||
{
|
||||
sceLibKernel.Error("sceKernelDeleteThread(threadId=0x%x)", threadId);
|
||||
sceLibKernel.Warning("sceKernelDeleteThread(threadId=0x%x)", threadId);
|
||||
|
||||
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(threadId, CPU_THREAD_ARMv7);
|
||||
|
||||
@ -125,7 +125,7 @@ s32 sceKernelDeleteThread(s32 threadId)
|
||||
|
||||
s32 sceKernelExitDeleteThread(ARMv7Context& context, s32 exitStatus)
|
||||
{
|
||||
sceLibKernel.Error("sceKernelExitDeleteThread(exitStatus=0x%x)", exitStatus);
|
||||
sceLibKernel.Warning("sceKernelExitDeleteThread(exitStatus=0x%x)", exitStatus);
|
||||
|
||||
// exit status is stored in r0
|
||||
context.thread.Stop();
|
||||
@ -261,7 +261,7 @@ s32 sceKernelDelayThreadCB(u32 usec)
|
||||
|
||||
s32 sceKernelWaitThreadEnd(s32 threadId, vm::psv::ptr<s32> pExitStatus, vm::psv::ptr<u32> pTimeout)
|
||||
{
|
||||
sceLibKernel.Error("sceKernelWaitThreadEnd(threadId=0x%x, pExitStatus=0x%x, pTimeout=0x%x)", threadId, pExitStatus, pTimeout);
|
||||
sceLibKernel.Warning("sceKernelWaitThreadEnd(threadId=0x%x, pExitStatus=0x%x, pTimeout=0x%x)", threadId, pExitStatus, pTimeout);
|
||||
|
||||
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(threadId, CPU_THREAD_ARMv7);
|
||||
|
||||
|
@ -16,7 +16,7 @@ namespace sce_libc_func
|
||||
{
|
||||
void __cxa_atexit(vm::psv::ptr<atexit_func_t> func, vm::psv::ptr<void> arg, vm::psv::ptr<void> dso)
|
||||
{
|
||||
sceLibc.Error("__cxa_atexit(func=0x%x, arg=0x%x, dso=0x%x)", func, arg, dso);
|
||||
sceLibc.Warning("__cxa_atexit(func=0x%x, arg=0x%x, dso=0x%x)", func, arg, dso);
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
@ -28,7 +28,7 @@ namespace sce_libc_func
|
||||
|
||||
void __aeabi_atexit(vm::psv::ptr<void> arg, vm::psv::ptr<atexit_func_t> func, vm::psv::ptr<void> dso)
|
||||
{
|
||||
sceLibc.Error("__aeabi_atexit(arg=0x%x, func=0x%x, dso=0x%x)", arg, func, dso);
|
||||
sceLibc.Warning("__aeabi_atexit(arg=0x%x, func=0x%x, dso=0x%x)", arg, func, dso);
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
@ -40,7 +40,7 @@ namespace sce_libc_func
|
||||
|
||||
void exit(ARMv7Context& context)
|
||||
{
|
||||
sceLibc.Error("exit()");
|
||||
sceLibc.Warning("exit()");
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
@ -117,7 +117,7 @@ namespace sce_libc_func
|
||||
|
||||
void printf(ARMv7Context& context, vm::psv::ptr<const char> fmt) // va_args...
|
||||
{
|
||||
sceLibc.Error("printf(fmt=0x%x)", fmt);
|
||||
sceLibc.Warning("printf(fmt=0x%x)", fmt);
|
||||
|
||||
sceLibc.Notice("*** *fmt = '%s'", fmt.get_ptr());
|
||||
|
||||
@ -126,7 +126,7 @@ namespace sce_libc_func
|
||||
|
||||
void sprintf(ARMv7Context& context, vm::psv::ptr<char> str, vm::psv::ptr<const char> fmt) // va_args...
|
||||
{
|
||||
sceLibc.Error("sprintf(str=0x%x, fmt=0x%x)", str, fmt);
|
||||
sceLibc.Warning("sprintf(str=0x%x, fmt=0x%x)", str, fmt);
|
||||
|
||||
sceLibc.Notice("*** *fmt = '%s'", fmt.get_ptr());
|
||||
|
||||
@ -139,28 +139,28 @@ namespace sce_libc_func
|
||||
|
||||
void __cxa_set_dso_handle_main(vm::psv::ptr<void> dso)
|
||||
{
|
||||
sceLibc.Error("__cxa_set_dso_handle_main(dso=0x%x)", dso);
|
||||
sceLibc.Warning("__cxa_set_dso_handle_main(dso=0x%x)", dso);
|
||||
|
||||
g_dso = dso;
|
||||
}
|
||||
|
||||
void memcpy(vm::psv::ptr<void> dst, vm::psv::ptr<const void> src, u32 size)
|
||||
{
|
||||
sceLibc.Error("memcpy(dst=0x%x, src=0x%x, size=0x%x)", dst, src, size);
|
||||
sceLibc.Warning("memcpy(dst=0x%x, src=0x%x, size=0x%x)", dst, src, size);
|
||||
|
||||
::memcpy(dst.get_ptr(), src.get_ptr(), size);
|
||||
}
|
||||
|
||||
void memset(vm::psv::ptr<void> dst, s32 value, u32 size)
|
||||
{
|
||||
sceLibc.Error("memset(dst=0x%x, value=%d, size=0x%x)", dst, value, size);
|
||||
sceLibc.Warning("memset(dst=0x%x, value=%d, size=0x%x)", dst, value, size);
|
||||
|
||||
::memset(dst.get_ptr(), value, size);
|
||||
}
|
||||
|
||||
void _Assert(vm::psv::ptr<const char> text, vm::psv::ptr<const char> func)
|
||||
{
|
||||
sceLibc.Error("_Assert(text=0x%x, func=0x%x)", text, func);
|
||||
sceLibc.Warning("_Assert(text=0x%x, func=0x%x)", text, func);
|
||||
|
||||
LOG_ERROR(TTY, "%s : %s\n", func.get_ptr(), text.get_ptr());
|
||||
Emu.Pause();
|
||||
|
@ -8,20 +8,17 @@ namespace sce_libstdcxx_func
|
||||
{
|
||||
void __aeabi_unwind_cpp_pr0()
|
||||
{
|
||||
sceLibstdcxx.Todo(__FUNCTION__);
|
||||
Emu.Pause();
|
||||
throw __FUNCTION__;
|
||||
}
|
||||
|
||||
void __aeabi_unwind_cpp_pr1()
|
||||
{
|
||||
sceLibstdcxx.Todo(__FUNCTION__);
|
||||
Emu.Pause();
|
||||
throw __FUNCTION__;
|
||||
}
|
||||
|
||||
void __aeabi_unwind_cpp_pr2()
|
||||
{
|
||||
sceLibstdcxx.Todo(__FUNCTION__);
|
||||
Emu.Pause();
|
||||
throw __FUNCTION__;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,48 +2,242 @@
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/ARMv7/PSVFuncList.h"
|
||||
|
||||
#include "Emu/SysCalls/lv2/sys_time.h"
|
||||
|
||||
#define RETURN_ERROR(code) { Emu.Pause(); scePerf.Error("%s() failed: %s", __FUNCTION__, #code); return code; }
|
||||
|
||||
extern psv_log_base scePerf;
|
||||
|
||||
s32 scePerfArmPmonReset(s32 threadId)
|
||||
enum
|
||||
{
|
||||
scePerf.Todo("scePerfArmPmonReset(threadId=0x%x)", threadId);
|
||||
// Error Codes
|
||||
SCE_PERF_ERROR_INVALID_ARGUMENT = 0x80580000,
|
||||
};
|
||||
|
||||
enum : s32
|
||||
{
|
||||
// Thread IDs
|
||||
SCE_PERF_ARM_PMON_THREAD_ID_ALL = -1,
|
||||
SCE_PERF_ARM_PMON_THREAD_ID_SELF = 0,
|
||||
};
|
||||
|
||||
enum : u32
|
||||
{
|
||||
// Counter Numbers
|
||||
SCE_PERF_ARM_PMON_CYCLE_COUNTER = 31,
|
||||
SCE_PERF_ARM_PMON_COUNTER_5 = 5,
|
||||
SCE_PERF_ARM_PMON_COUNTER_4 = 4,
|
||||
SCE_PERF_ARM_PMON_COUNTER_3 = 3,
|
||||
SCE_PERF_ARM_PMON_COUNTER_2 = 2,
|
||||
SCE_PERF_ARM_PMON_COUNTER_1 = 1,
|
||||
SCE_PERF_ARM_PMON_COUNTER_0 = 0,
|
||||
|
||||
// Counter Masks
|
||||
SCE_PERF_ARM_PMON_COUNTER_MASK_5 = 0x20,
|
||||
SCE_PERF_ARM_PMON_COUNTER_MASK_4 = 0x10,
|
||||
SCE_PERF_ARM_PMON_COUNTER_MASK_3 = 0x08,
|
||||
SCE_PERF_ARM_PMON_COUNTER_MASK_2 = 0x04,
|
||||
SCE_PERF_ARM_PMON_COUNTER_MASK_1 = 0x02,
|
||||
SCE_PERF_ARM_PMON_COUNTER_MASK_0 = 0x01,
|
||||
SCE_PERF_ARM_PMON_COUNTER_MASK_ALL = 0x3f,
|
||||
};
|
||||
|
||||
enum : u8
|
||||
{
|
||||
// Performance Counter Events
|
||||
SCE_PERF_ARM_PMON_SOFT_INCREMENT = 0x00,
|
||||
SCE_PERF_ARM_PMON_ICACHE_MISS = 0x01,
|
||||
SCE_PERF_ARM_PMON_ITLB_MISS = 0x02,
|
||||
SCE_PERF_ARM_PMON_DCACHE_MISS = 0x03,
|
||||
SCE_PERF_ARM_PMON_DCACHE_ACCESS = 0x04,
|
||||
SCE_PERF_ARM_PMON_DTLB_MISS = 0x05,
|
||||
SCE_PERF_ARM_PMON_DATA_READ = 0x06,
|
||||
SCE_PERF_ARM_PMON_DATA_WRITE = 0x07,
|
||||
SCE_PERF_ARM_PMON_EXCEPTION_TAKEN = 0x09,
|
||||
SCE_PERF_ARM_PMON_EXCEPTION_RETURN = 0x0A,
|
||||
SCE_PERF_ARM_PMON_WRITE_CONTEXTID = 0x0B,
|
||||
SCE_PERF_ARM_PMON_SOFT_CHANGEPC = 0x0C,
|
||||
SCE_PERF_ARM_PMON_IMMEDIATE_BRANCH = 0x0D,
|
||||
SCE_PERF_ARM_PMON_UNALIGNED = 0x0F,
|
||||
SCE_PERF_ARM_PMON_BRANCH_MISPREDICT = 0x10,
|
||||
SCE_PERF_ARM_PMON_PREDICT_BRANCH = 0x12,
|
||||
SCE_PERF_ARM_PMON_COHERENT_LF_MISS = 0x50,
|
||||
SCE_PERF_ARM_PMON_COHERENT_LF_HIT = 0x51,
|
||||
SCE_PERF_ARM_PMON_ICACHE_STALL = 0x60,
|
||||
SCE_PERF_ARM_PMON_DCACHE_STALL = 0x61,
|
||||
SCE_PERF_ARM_PMON_MAINTLB_STALL = 0x62,
|
||||
SCE_PERF_ARM_PMON_STREX_PASSED = 0x63,
|
||||
SCE_PERF_ARM_PMON_STREX_FAILED = 0x64,
|
||||
SCE_PERF_ARM_PMON_DATA_EVICTION = 0x65,
|
||||
SCE_PERF_ARM_PMON_ISSUE_NO_DISPATCH = 0x66,
|
||||
SCE_PERF_ARM_PMON_ISSUE_EMPTY = 0x67,
|
||||
SCE_PERF_ARM_PMON_INST_RENAME = 0x68,
|
||||
SCE_PERF_ARM_PMON_PREDICT_FUNC_RET = 0x6E,
|
||||
SCE_PERF_ARM_PMON_MAIN_PIPE = 0x70,
|
||||
SCE_PERF_ARM_PMON_SECOND_PIPE = 0x71,
|
||||
SCE_PERF_ARM_PMON_LS_PIPE = 0x72,
|
||||
SCE_PERF_ARM_PMON_FPU_RENAME = 0x73,
|
||||
SCE_PERF_ARM_PMON_PLD_STALL = 0x80,
|
||||
SCE_PERF_ARM_PMON_WRITE_STALL = 0x81,
|
||||
SCE_PERF_ARM_PMON_INST_MAINTLB_STALL = 0x82,
|
||||
SCE_PERF_ARM_PMON_DATA_MAINTLB_STALL = 0x83,
|
||||
SCE_PERF_ARM_PMON_INST_UTLB_STALL = 0x84,
|
||||
SCE_PERF_ARM_PMON_DATA_UTLB_STALL = 0x85,
|
||||
SCE_PERF_ARM_PMON_DMB_STALL = 0x86,
|
||||
SCE_PERF_ARM_PMON_INTEGER_CLOCK = 0x8A,
|
||||
SCE_PERF_ARM_PMON_DATAENGINE_CLOCK = 0x8B,
|
||||
SCE_PERF_ARM_PMON_ISB = 0x90,
|
||||
SCE_PERF_ARM_PMON_DSB = 0x91,
|
||||
SCE_PERF_ARM_PMON_DMB = 0x92,
|
||||
SCE_PERF_ARM_PMON_EXT_INTERRUPT = 0x93,
|
||||
SCE_PERF_ARM_PMON_PLE_LINE_REQ_COMPLETED = 0xA0,
|
||||
SCE_PERF_ARM_PMON_PLE_CHANNEL_SKIPPED = 0xA1,
|
||||
SCE_PERF_ARM_PMON_PLE_FIFO_FLUSH = 0xA2,
|
||||
SCE_PERF_ARM_PMON_PLE_REQ_COMPLETED = 0xA3,
|
||||
SCE_PERF_ARM_PMON_PLE_FIFO_OVERFLOW = 0xA4,
|
||||
SCE_PERF_ARM_PMON_PLE_REQ_PROGRAMMED = 0xA5,
|
||||
};
|
||||
|
||||
s32 scePerfArmPmonReset(ARMv7Context& context, s32 threadId)
|
||||
{
|
||||
scePerf.Warning("scePerfArmPmonReset(threadId=0x%x)", threadId);
|
||||
|
||||
if (threadId != SCE_PERF_ARM_PMON_THREAD_ID_SELF)
|
||||
{
|
||||
throw __FUNCTION__;
|
||||
}
|
||||
|
||||
context.counters = {};
|
||||
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
s32 scePerfArmPmonSelectEvent(s32 threadId, u32 counter, u8 eventCode)
|
||||
s32 scePerfArmPmonSelectEvent(ARMv7Context& context, s32 threadId, u32 counter, u8 eventCode)
|
||||
{
|
||||
throw __FUNCTION__;
|
||||
scePerf.Warning("scePerfArmPmonSelectEvent(threadId=0x%x, counter=0x%x, eventCode=0x%x)", threadId, counter, eventCode);
|
||||
|
||||
if (threadId != SCE_PERF_ARM_PMON_THREAD_ID_SELF)
|
||||
{
|
||||
throw __FUNCTION__;
|
||||
}
|
||||
|
||||
if (counter >= 6)
|
||||
{
|
||||
RETURN_ERROR(SCE_PERF_ERROR_INVALID_ARGUMENT);
|
||||
}
|
||||
|
||||
u32 value = 0; // initial value
|
||||
|
||||
switch (eventCode)
|
||||
{
|
||||
case SCE_PERF_ARM_PMON_SOFT_INCREMENT: break;
|
||||
|
||||
case SCE_PERF_ARM_PMON_BRANCH_MISPREDICT:
|
||||
case SCE_PERF_ARM_PMON_DCACHE_MISS:
|
||||
case SCE_PERF_ARM_PMON_UNALIGNED:
|
||||
{
|
||||
value = 1; // these events will probably never be implemented
|
||||
break;
|
||||
}
|
||||
|
||||
case SCE_PERF_ARM_PMON_PREDICT_BRANCH:
|
||||
case SCE_PERF_ARM_PMON_DCACHE_ACCESS:
|
||||
{
|
||||
value = 1000; // these events will probably never be implemented
|
||||
break;
|
||||
}
|
||||
|
||||
default: throw "scePerfArmPmonSelectEvent(): unknown event requested";
|
||||
}
|
||||
|
||||
context.counters[counter].event = eventCode;
|
||||
context.counters[counter].value = value;
|
||||
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
s32 scePerfArmPmonStart(s32 threadId)
|
||||
s32 scePerfArmPmonStart(ARMv7Context& context, s32 threadId)
|
||||
{
|
||||
throw __FUNCTION__;
|
||||
scePerf.Warning("scePerfArmPmonStart(threadId=0x%x)", threadId);
|
||||
|
||||
if (threadId != SCE_PERF_ARM_PMON_THREAD_ID_SELF)
|
||||
{
|
||||
throw __FUNCTION__;
|
||||
}
|
||||
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
s32 scePerfArmPmonStop(s32 threadId)
|
||||
s32 scePerfArmPmonStop(ARMv7Context& context, s32 threadId)
|
||||
{
|
||||
throw __FUNCTION__;
|
||||
scePerf.Warning("scePerfArmPmonStop(threadId=0x%x)");
|
||||
|
||||
if (threadId != SCE_PERF_ARM_PMON_THREAD_ID_SELF)
|
||||
{
|
||||
throw __FUNCTION__;
|
||||
}
|
||||
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
s32 scePerfArmPmonGetCounterValue(s32 threadId, u32 counter, vm::psv::ptr<u32> pValue)
|
||||
s32 scePerfArmPmonGetCounterValue(ARMv7Context& context, s32 threadId, u32 counter, vm::psv::ptr<u32> pValue)
|
||||
{
|
||||
throw __FUNCTION__;
|
||||
scePerf.Warning("scePerfArmPmonGetCounterValue(threadId=0x%x, counter=%d, pValue=0x%x)", threadId, counter, pValue);
|
||||
|
||||
if (threadId != SCE_PERF_ARM_PMON_THREAD_ID_SELF)
|
||||
{
|
||||
throw __FUNCTION__;
|
||||
}
|
||||
|
||||
if (counter >= 6 && counter != SCE_PERF_ARM_PMON_CYCLE_COUNTER)
|
||||
{
|
||||
RETURN_ERROR(SCE_PERF_ERROR_INVALID_ARGUMENT);
|
||||
}
|
||||
|
||||
if (counter < 6)
|
||||
{
|
||||
*pValue = context.counters[counter].value;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw "scePerfArmPmonGetCounterValue(): cycle counter requested";
|
||||
}
|
||||
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
s32 scePerfArmPmonSoftwareIncrement(u32 mask)
|
||||
s32 scePerfArmPmonSoftwareIncrement(ARMv7Context& context, u32 mask)
|
||||
{
|
||||
throw __FUNCTION__;
|
||||
scePerf.Warning("scePerfArmPmonSoftwareIncrement(mask=0x%x)", mask);
|
||||
|
||||
if (mask > SCE_PERF_ARM_PMON_COUNTER_MASK_ALL)
|
||||
{
|
||||
RETURN_ERROR(SCE_PERF_ERROR_INVALID_ARGUMENT);
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < 6; i++, mask >>= 1)
|
||||
{
|
||||
if (mask & 1)
|
||||
{
|
||||
context.counters[i].value++;
|
||||
}
|
||||
}
|
||||
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
u64 scePerfGetTimebaseValue()
|
||||
{
|
||||
throw __FUNCTION__;
|
||||
scePerf.Warning("scePerfGetTimebaseValue()");
|
||||
|
||||
return get_system_time();
|
||||
}
|
||||
|
||||
u32 scePerfGetTimebaseFrequency()
|
||||
{
|
||||
throw __FUNCTION__;
|
||||
scePerf.Warning("scePerfGetTimebaseFrequency()");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
s32 _sceRazorCpuInit(vm::psv::ptr<const void> pBufferBase, u32 bufferSize, u32 numPerfCounters, vm::psv::ptr<vm::psv::ptr<u32>> psceRazorVars)
|
||||
|
@ -93,6 +93,37 @@ namespace loader
|
||||
case MACHINE_MIPS: break;
|
||||
case MACHINE_ARM:
|
||||
{
|
||||
struct psv_libc_param_t
|
||||
{
|
||||
u32 size; // 0x0000001c
|
||||
u32 unk1; // 0x00000000
|
||||
|
||||
vm::psv::ptr<u32> sceLibcHeapSize;
|
||||
vm::psv::ptr<u32> sceLibcHeapSizeDefault;
|
||||
vm::psv::ptr<u32> sceLibcHeapExtendedAlloc;
|
||||
vm::psv::ptr<u32> sceLibcHeapDelayedAlloc;
|
||||
|
||||
u32 unk2;
|
||||
};
|
||||
|
||||
struct psv_process_param_t
|
||||
{
|
||||
u32 size; // 0x00000030
|
||||
u32 unk1; // 'PSP2'
|
||||
u32 unk2; // 0x00000005
|
||||
u32 unk3;
|
||||
|
||||
vm::psv::ptr<const char> sceUserMainThreadName;
|
||||
vm::psv::ptr<s32> sceUserMainThreadPriority;
|
||||
vm::psv::ptr<u32> sceUserMainThreadStackSize;
|
||||
vm::psv::ptr<u32> sceUserMainThreadAttribute;
|
||||
vm::psv::ptr<const char> sceProcessName;
|
||||
vm::psv::ptr<u32> sce_process_preload_disabled;
|
||||
vm::psv::ptr<u32> sceUserMainThreadCpuAffinityMask;
|
||||
|
||||
vm::psv::ptr<psv_libc_param_t> __sce_libcparam;
|
||||
};
|
||||
|
||||
initialize_psv_modules();
|
||||
|
||||
auto armv7_thr_stop_data = vm::psv::ptr<u32>::make(Memory.PSV.RAM.AllocAlign(3 * 4));
|
||||
@ -104,10 +135,11 @@ namespace loader
|
||||
u32 fnid_addr = 0;
|
||||
u32 code_start = 0;
|
||||
u32 code_end = 0;
|
||||
|
||||
u32 vnid_addr = 0;
|
||||
std::unordered_map<u32, u32> vnid_list;
|
||||
|
||||
auto proc_param = vm::psv::ptr<psv_process_param_t>::make(0);
|
||||
|
||||
for (auto& shdr : m_shdrs)
|
||||
{
|
||||
// get secton name
|
||||
@ -130,24 +162,40 @@ namespace loader
|
||||
code_start = shdr.data_le.sh_addr;
|
||||
code_end = shdr.data_le.sh_size + code_start;
|
||||
}
|
||||
else if (!strcmp(name.c_str(), ".sceModuleInfo.rodata"))
|
||||
else if (!strcmp(name.c_str(), ".sceExport.rodata"))
|
||||
{
|
||||
LOG_NOTICE(LOADER, ".sceModuleInfo.rodata analysis...");
|
||||
LOG_NOTICE(LOADER, ".sceExport.rodata analysis...");
|
||||
|
||||
auto code = vm::psv::ptr<const u32>::make(shdr.data_le.sh_addr);
|
||||
auto enid = vm::psv::ptr<const u32>::make(shdr.data_le.sh_addr);
|
||||
auto edata = vm::psv::ptr<const u32>::make(enid.addr() + shdr.data_le.sh_size / 2);
|
||||
|
||||
// very rough way to find the entry point
|
||||
while (code[0] != 0xffffffffu)
|
||||
for (u32 j = 0; j < shdr.data_le.sh_size / 8; j++)
|
||||
{
|
||||
entry = code[0] + 0x81000000;
|
||||
code++;
|
||||
|
||||
if (code.addr() >= shdr.data_le.sh_addr + shdr.data_le.sh_size)
|
||||
switch (const u32 nid = enid[j])
|
||||
{
|
||||
LOG_ERROR(LOADER, "Unable to find entry point in .sceModuleInfo.rodata");
|
||||
entry = 0;
|
||||
case 0x935cd196: // set entry point
|
||||
{
|
||||
entry = edata[j];
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x6c2224ba: // __sce_moduleinfo
|
||||
{
|
||||
// currently nothing, but it should theoretically be the root of analysis instead of section name comparison
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x70fba1e7: // __sce_process_param
|
||||
{
|
||||
proc_param.set(edata[j]);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
LOG_ERROR(LOADER, "Unknown export 0x%08x (addr=0x%08x)", nid, edata[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!strcmp(name.c_str(), ".sceFNID.rodata"))
|
||||
@ -320,10 +368,44 @@ namespace loader
|
||||
}
|
||||
}
|
||||
|
||||
LOG_NOTICE(LOADER, "__sce_process_param(addr=0x%x) analysis...", proc_param);
|
||||
|
||||
if (proc_param->size != 0x30 || proc_param->unk1 != *(u32*)"PSP2" || proc_param->unk2 != 5)
|
||||
{
|
||||
LOG_ERROR(LOADER, "__sce_process_param: unexpected data found (size=0x%x, 0x%x, 0x%x, 0x%x)", proc_param->size, proc_param->unk1, proc_param->unk2, proc_param->unk3);
|
||||
}
|
||||
|
||||
LOG_NOTICE(LOADER, "*** &sceUserMainThreadName = 0x%x", proc_param->sceUserMainThreadName);
|
||||
LOG_NOTICE(LOADER, "*** &sceUserMainThreadPriority = 0x%x", proc_param->sceUserMainThreadPriority);
|
||||
LOG_NOTICE(LOADER, "*** &sceUserMainThreadStackSize = 0x%x", proc_param->sceUserMainThreadStackSize);
|
||||
LOG_NOTICE(LOADER, "*** &sceUserMainThreadAttribute = 0x%x", proc_param->sceUserMainThreadAttribute);
|
||||
LOG_NOTICE(LOADER, "*** &sceProcessName = 0x%x", proc_param->sceProcessName);
|
||||
LOG_NOTICE(LOADER, "*** &sce_process_preload_disabled = 0x%x", proc_param->sce_process_preload_disabled);
|
||||
LOG_NOTICE(LOADER, "*** &sceUserMainThreadCpuAffinityMask = 0x%x", proc_param->sceUserMainThreadCpuAffinityMask);
|
||||
|
||||
auto libc_param = proc_param->__sce_libcparam;
|
||||
|
||||
LOG_NOTICE(LOADER, "__sce_libcparam(addr=0x%x) analysis...", libc_param);
|
||||
|
||||
if (libc_param->size != 0x1c || libc_param->unk1)
|
||||
{
|
||||
LOG_ERROR(LOADER, "__sce_libcparam: unexpected data found (size=0x%x, 0x%x, 0x%x)", libc_param->size, libc_param->unk1, libc_param->unk2);
|
||||
}
|
||||
|
||||
LOG_NOTICE(LOADER, "*** &sceLibcHeapSize = 0x%x", libc_param->sceLibcHeapSize);
|
||||
LOG_NOTICE(LOADER, "*** &sceLibcHeapSizeDefault = 0x%x", libc_param->sceLibcHeapSizeDefault);
|
||||
LOG_NOTICE(LOADER, "*** &sceLibcHeapExtendedAlloc = 0x%x", libc_param->sceLibcHeapExtendedAlloc);
|
||||
LOG_NOTICE(LOADER, "*** &sceLibcHeapDelayedAlloc = 0x%x", libc_param->sceLibcHeapDelayedAlloc);
|
||||
|
||||
armv7_init_tls();
|
||||
armv7_decoder_initialize(code_start, code_end);
|
||||
|
||||
armv7_thread(entry & ~1 /* TODO: Thumb/ARM encoding selection */, "main_thread").args({ Emu.GetPath(), "-emu" }).run();
|
||||
const std::string& thread_name = proc_param->sceUserMainThreadName ? proc_param->sceUserMainThreadName.get_ptr() : "main_thread";
|
||||
const u32 stack_size = proc_param->sceUserMainThreadStackSize ? *proc_param->sceUserMainThreadStackSize : 0;
|
||||
const u32 priority = proc_param->sceUserMainThreadPriority ? *proc_param->sceUserMainThreadPriority : 0;
|
||||
|
||||
/* TODO: Thumb/ARM encoding selection */
|
||||
armv7_thread(entry & ~1, thread_name, stack_size, priority).args({ Emu.GetPath(), "-emu" }).run();
|
||||
break;
|
||||
}
|
||||
case MACHINE_SPU: spu_thread(m_ehdr.is_le() ? m_ehdr.data_le.e_entry : m_ehdr.data_be.e_entry, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); break;
|
||||
|
Loading…
Reference in New Issue
Block a user