mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 03:25:16 +00:00
commit
75e81bc969
23 changed files with 439 additions and 334 deletions
|
@ -6,6 +6,12 @@
|
|||
#define thread_local __thread
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define noinline __declspec(noinline)
|
||||
#else
|
||||
#define noinline __attribute__((noinline))
|
||||
#endif
|
||||
|
||||
template<size_t size>
|
||||
void strcpy_trunc(char (&dst)[size], const std::string& src)
|
||||
{
|
||||
|
|
2
asmjit
2
asmjit
|
@ -1 +1 @@
|
|||
Subproject commit a66efd54609aab7dd98e34c069937f34aa7c8f95
|
||||
Subproject commit 3363e4138b003be36dfb63cf8c63cf360f04276f
|
|
@ -23,31 +23,55 @@
|
|||
<ClCompile Include="..\asmjit\src\asmjit\base\codegen.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\compiler.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\constpool.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\containers.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\context.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\cpuinfo.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\cputicks.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\error.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\globals.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\intutil.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\logger.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\operand.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\podvector.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\runtime.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\string.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\vmem.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\zone.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\contrib\winremoteruntime.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86assembler.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86compiler.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86context.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86cpuinfo.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86func.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86inst.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86operand.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86regs.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86util.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86operand_regs.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86scheduler.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\assembler.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\codegen.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\compiler.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\constpool.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\containers.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\context_p.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\cpuinfo.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\cputicks.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\error.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\globals.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\intutil.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\lock.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\logger.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\operand.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\runtime.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\string.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\vectypes.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\vmem.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\zone.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\x86\x86assembler.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\x86\x86compiler.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\x86\x86context_p.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\x86\x86cpuinfo.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\x86\x86inst.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\x86\x86operand.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\x86\x86scheduler_p.h" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{AC40FF01-426E-4838-A317-66354CEFAE88}</ProjectGuid>
|
||||
|
|
|
@ -1,34 +1,58 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86assembler.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86compiler.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86context.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86cpuinfo.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86func.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\contrib\winremoteruntime.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\assembler.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\codegen.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\compiler.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\constpool.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\containers.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\context.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\cpuinfo.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\cputicks.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\error.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\globals.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\intutil.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\logger.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\podvector.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\operand.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\runtime.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\string.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\vmem.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\zone.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\constpool.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\base\operand.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86assembler.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86compiler.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86context.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86cpuinfo.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86inst.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86operand.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86regs.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86util.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86operand_regs.cpp" />
|
||||
<ClCompile Include="..\asmjit\src\asmjit\x86\x86scheduler.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\asmjit\src\asmjit\x86\x86assembler.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\x86\x86compiler.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\x86\x86context_p.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\x86\x86cpuinfo.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\x86\x86inst.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\x86\x86operand.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\x86\x86scheduler_p.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\assembler.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\codegen.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\compiler.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\constpool.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\containers.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\context_p.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\cpuinfo.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\cputicks.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\error.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\globals.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\intutil.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\lock.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\logger.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\operand.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\runtime.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\string.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\vectypes.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\vmem.h" />
|
||||
<ClInclude Include="..\asmjit\src\asmjit\base\zone.h" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -21,8 +21,8 @@ public:
|
|||
virtual u8 DecodeMemory(const u64 address)
|
||||
{
|
||||
using namespace ARMv7_opcodes;
|
||||
const u16 code0 = Memory.Read16(address);
|
||||
const u16 code1 = Memory.Read16(address + 2);
|
||||
const u16 code0 = Memory.PSV.Read16(address);
|
||||
const u16 code1 = Memory.PSV.Read16(address + 2);
|
||||
|
||||
switch(code0 >> 12) //15 - 12
|
||||
{
|
||||
|
|
|
@ -275,7 +275,7 @@ protected:
|
|||
if(regs_list & mask)
|
||||
{
|
||||
CPU.SP -= 4;
|
||||
Memory.Write32(CPU.SP, CPU.read_gpr(i));
|
||||
Memory.PSV.Write32(CPU.SP, CPU.read_gpr(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -286,7 +286,7 @@ protected:
|
|||
{
|
||||
if(regs_list & mask)
|
||||
{
|
||||
CPU.write_gpr(i, Memory.Read32(CPU.SP));
|
||||
CPU.write_gpr(i, Memory.PSV.Read32(CPU.SP));
|
||||
CPU.SP += 4;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -285,7 +285,7 @@ void CPUThread::ExecOnce()
|
|||
void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp)
|
||||
{
|
||||
const u64 addr = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)Memory.GetBaseAddr();
|
||||
if (addr < 0x100000000 && u == EXCEPTION_ACCESS_VIOLATION)
|
||||
if (u == EXCEPTION_ACCESS_VIOLATION && addr < 0x100000000)
|
||||
{
|
||||
// TODO: allow recovering from a page fault
|
||||
//GetCurrentPPUThread().Stop();
|
||||
|
@ -317,6 +317,8 @@ void CPUThread::Task()
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<u64> trace;
|
||||
|
||||
#ifdef _WIN32
|
||||
_set_se_translator(_se_translator);
|
||||
#else
|
||||
|
@ -339,6 +341,7 @@ void CPUThread::Task()
|
|||
}
|
||||
|
||||
Step();
|
||||
//if (PC - 0x13ED4 < 0x288) trace.push_back(PC);
|
||||
NextPc(m_dec->DecodeMemory(PC + m_offset));
|
||||
|
||||
if (status == CPUThread_Step)
|
||||
|
@ -357,6 +360,8 @@ void CPUThread::Task()
|
|||
}
|
||||
}
|
||||
|
||||
for (auto& v : trace) LOG_NOTICE(PPU, "PC = 0x%llx", v);
|
||||
|
||||
if (Ini.HLELogging.GetValue()) LOG_NOTICE(PPU, "%s leave", CPUThread::GetFName().c_str());
|
||||
}
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ public:
|
|||
if (#a1[0] == 'r') XmmInvalidate(a1); \
|
||||
if (#a2[0] == 'r') XmmInvalidate(a2); \
|
||||
if (#a3[0] == 'r') XmmInvalidate(a3); \
|
||||
X86X64CallNode* call##a0 = c.call(imm_ptr(reinterpret_cast<void*>(&opwr_##a0::opcode)), kFuncConvHost, FuncBuilder4<FnVoid, u32, u32, u32, u32>()); \
|
||||
X86CallNode* call##a0 = c.call(imm_ptr(reinterpret_cast<void*>(&opwr_##a0::opcode)), kFuncConvHost, FuncBuilder4<void, u32, u32, u32, u32>()); \
|
||||
call##a0->setArg(0, imm_u(a0)); \
|
||||
call##a0->setArg(1, imm_u(a1)); \
|
||||
call##a0->setArg(2, imm_u(a2)); \
|
||||
|
@ -163,24 +163,24 @@ private:
|
|||
SPURecompilerCore& rec;
|
||||
|
||||
public:
|
||||
Compiler* compiler;
|
||||
X86Compiler* compiler;
|
||||
bool do_finalize;
|
||||
// input:
|
||||
GpVar* cpu_var;
|
||||
GpVar* ls_var;
|
||||
GpVar* imm_var;
|
||||
GpVar* g_imm_var;
|
||||
X86GpVar* cpu_var;
|
||||
X86GpVar* ls_var;
|
||||
X86GpVar* imm_var;
|
||||
X86GpVar* g_imm_var;
|
||||
// output:
|
||||
GpVar* pos_var;
|
||||
X86GpVar* pos_var;
|
||||
// temporary:
|
||||
GpVar* addr;
|
||||
GpVar* qw0;
|
||||
GpVar* qw1;
|
||||
GpVar* qw2;
|
||||
X86GpVar* addr;
|
||||
X86GpVar* qw0;
|
||||
X86GpVar* qw1;
|
||||
X86GpVar* qw2;
|
||||
|
||||
struct XmmLink
|
||||
{
|
||||
XmmVar* data;
|
||||
X86XmmVar* data;
|
||||
s8 reg;
|
||||
bool taken;
|
||||
mutable bool got;
|
||||
|
@ -443,7 +443,7 @@ private:
|
|||
}
|
||||
};
|
||||
c.mov(cpu_qword(PC), (u32)CPU.PC);
|
||||
X86X64CallNode* call = c.call(imm_ptr(reinterpret_cast<void*>(&STOP_wrapper::STOP)), kFuncConvHost, FuncBuilder1<FnVoid, u32>());
|
||||
X86CallNode* call = c.call(imm_ptr(reinterpret_cast<void*>(&STOP_wrapper::STOP)), kFuncConvHost, FuncBuilder1<void, u32>());
|
||||
call->setArg(0, imm_u(code));
|
||||
c.mov(*pos_var, (CPU.PC >> 2) + 1);
|
||||
do_finalize = true;
|
||||
|
@ -1114,7 +1114,7 @@ private:
|
|||
|
||||
/*XmmInvalidate(rt);
|
||||
|
||||
GpVar v(c, kVarTypeUInt32);
|
||||
X86GpVar v(c, kVarTypeUInt32);
|
||||
c.mov(v, cpu_dword(GPR[rt]._u32[3]));
|
||||
switch (ra)
|
||||
{
|
||||
|
|
|
@ -13,12 +13,19 @@
|
|||
static const g_imm_table_struct g_imm_table;
|
||||
|
||||
SPURecompilerCore::SPURecompilerCore(SPUThread& cpu)
|
||||
: m_enc(new SPURecompiler(cpu, *this))
|
||||
, inter(new SPUInterpreter(cpu))
|
||||
, CPU(cpu)
|
||||
, first(true)
|
||||
: m_enc(new SPURecompiler(cpu, *this))
|
||||
, inter(new SPUInterpreter(cpu))
|
||||
, CPU(cpu)
|
||||
, first(true)
|
||||
{
|
||||
memset(entry, 0, sizeof(entry));
|
||||
X86CpuInfo inf;
|
||||
X86CpuUtil::detect(&inf);
|
||||
if (!inf.hasFeature(kX86CpuFeatureSse41))
|
||||
{
|
||||
LOG_ERROR(SPU, "SPU Recompiler requires SSE4.1 instruction set support");
|
||||
Emu.Pause();
|
||||
}
|
||||
}
|
||||
|
||||
SPURecompilerCore::~SPURecompilerCore()
|
||||
|
@ -42,7 +49,7 @@ void SPURecompilerCore::Compile(u16 pos)
|
|||
StringLogger stringLogger;
|
||||
stringLogger.setOption(kLoggerOptionBinaryForm, true);
|
||||
|
||||
Compiler compiler(&runtime);
|
||||
X86Compiler compiler(&runtime);
|
||||
m_enc->compiler = &compiler;
|
||||
compiler.setLogger(&stringLogger);
|
||||
|
||||
|
@ -51,40 +58,40 @@ void SPURecompilerCore::Compile(u16 pos)
|
|||
u32 excess = 0;
|
||||
entry[start].count = 0;
|
||||
|
||||
GpVar cpu_var(compiler, kVarTypeIntPtr, "cpu");
|
||||
X86GpVar cpu_var(compiler, kVarTypeIntPtr, "cpu");
|
||||
compiler.setArg(0, cpu_var);
|
||||
compiler.alloc(cpu_var);
|
||||
m_enc->cpu_var = &cpu_var;
|
||||
|
||||
GpVar ls_var(compiler, kVarTypeIntPtr, "ls");
|
||||
X86GpVar ls_var(compiler, kVarTypeIntPtr, "ls");
|
||||
compiler.setArg(1, ls_var);
|
||||
compiler.alloc(ls_var);
|
||||
m_enc->ls_var = &ls_var;
|
||||
|
||||
GpVar imm_var(compiler, kVarTypeIntPtr, "imm");
|
||||
X86GpVar imm_var(compiler, kVarTypeIntPtr, "imm");
|
||||
compiler.setArg(2, imm_var);
|
||||
compiler.alloc(imm_var);
|
||||
m_enc->imm_var = &imm_var;
|
||||
|
||||
GpVar g_imm_var(compiler, kVarTypeIntPtr, "g_imm");
|
||||
X86GpVar g_imm_var(compiler, kVarTypeIntPtr, "g_imm");
|
||||
compiler.setArg(3, g_imm_var);
|
||||
compiler.alloc(g_imm_var);
|
||||
m_enc->g_imm_var = &g_imm_var;
|
||||
|
||||
GpVar pos_var(compiler, kVarTypeUInt32, "pos");
|
||||
X86GpVar pos_var(compiler, kVarTypeUInt32, "pos");
|
||||
m_enc->pos_var = &pos_var;
|
||||
GpVar addr_var(compiler, kVarTypeUInt32, "addr");
|
||||
X86GpVar addr_var(compiler, kVarTypeUInt32, "addr");
|
||||
m_enc->addr = &addr_var;
|
||||
GpVar qw0_var(compiler, kVarTypeUInt64, "qw0");
|
||||
X86GpVar qw0_var(compiler, kVarTypeUInt64, "qw0");
|
||||
m_enc->qw0 = &qw0_var;
|
||||
GpVar qw1_var(compiler, kVarTypeUInt64, "qw1");
|
||||
X86GpVar qw1_var(compiler, kVarTypeUInt64, "qw1");
|
||||
m_enc->qw1 = &qw1_var;
|
||||
GpVar qw2_var(compiler, kVarTypeUInt64, "qw2");
|
||||
X86GpVar qw2_var(compiler, kVarTypeUInt64, "qw2");
|
||||
m_enc->qw2 = &qw2_var;
|
||||
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
{
|
||||
m_enc->xmm_var[i].data = new XmmVar(compiler, kVarTypeXmm, fmt::Format("reg_%d", i).c_str());
|
||||
m_enc->xmm_var[i].data = new X86XmmVar(compiler, kX86VarTypeXmm, fmt::Format("reg_%d", i).c_str());
|
||||
}
|
||||
|
||||
compiler.xor_(pos_var, pos_var);
|
||||
|
|
|
@ -362,7 +362,7 @@ public:
|
|||
|
||||
void Init()
|
||||
{
|
||||
m_index = 0;
|
||||
m_indval = 0;
|
||||
}
|
||||
|
||||
__forceinline bool Pop(u32& res)
|
||||
|
|
|
@ -364,193 +364,7 @@ bool MemoryBlockLE::Write128(const u64 addr, const u128 value)
|
|||
return true;
|
||||
}
|
||||
|
||||
//MemoryBase
|
||||
void MemoryBase::Write8(u64 addr, const u8 data)
|
||||
{
|
||||
if ((u32)addr == addr)
|
||||
{
|
||||
*(u8*)((u64)GetBaseAddr() + addr) = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr);
|
||||
Emu.Pause();
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryBase::Write16(u64 addr, const u16 data)
|
||||
{
|
||||
if ((u32)addr == addr)
|
||||
{
|
||||
*(u16*)((u64)GetBaseAddr() + addr) = re16(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr);
|
||||
Emu.Pause();
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryBase::Write32(u64 addr, const u32 data)
|
||||
{
|
||||
if ((u32)addr == addr)
|
||||
{
|
||||
if (addr < RAW_SPU_BASE_ADDR || (addr % RAW_SPU_OFFSET) < RAW_SPU_PROB_OFFSET || !RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET])
|
||||
{
|
||||
*(u32*)((u64)GetBaseAddr() + addr) = re32(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET]->Write32(addr, data);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr);
|
||||
Emu.Pause();
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryBase::Write64(u64 addr, const u64 data)
|
||||
{
|
||||
if ((u32)addr == addr)
|
||||
{
|
||||
*(u64*)((u64)GetBaseAddr() + addr) = re64(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr);
|
||||
Emu.Pause();
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryBase::Write128(u64 addr, const u128 data)
|
||||
{
|
||||
if ((u32)addr == addr)
|
||||
{
|
||||
*(u128*)((u64)GetBaseAddr() + addr) = re128(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr);
|
||||
Emu.Pause();
|
||||
}
|
||||
}
|
||||
|
||||
bool MemoryBase::Write8NN(u64 addr, const u8 data)
|
||||
{
|
||||
if(!IsGoodAddr(addr)) return false;
|
||||
Write8(addr, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MemoryBase::Write16NN(u64 addr, const u16 data)
|
||||
{
|
||||
if(!IsGoodAddr(addr, 2)) return false;
|
||||
Write16(addr, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MemoryBase::Write32NN(u64 addr, const u32 data)
|
||||
{
|
||||
if(!IsGoodAddr(addr, 4)) return false;
|
||||
Write32(addr, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MemoryBase::Write64NN(u64 addr, const u64 data)
|
||||
{
|
||||
if(!IsGoodAddr(addr, 8)) return false;
|
||||
Write64(addr, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MemoryBase::Write128NN(u64 addr, const u128 data)
|
||||
{
|
||||
if(!IsGoodAddr(addr, 16)) return false;
|
||||
Write128(addr, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
u8 MemoryBase::Read8(u64 addr)
|
||||
{
|
||||
if ((u32)addr == addr)
|
||||
{
|
||||
return *(u8*)((u64)GetBaseAddr() + addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr);
|
||||
Emu.Pause();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
u16 MemoryBase::Read16(u64 addr)
|
||||
{
|
||||
if ((u32)addr == addr)
|
||||
{
|
||||
return re16(*(u16*)((u64)GetBaseAddr() + addr));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr);
|
||||
Emu.Pause();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
u32 MemoryBase::Read32(u64 addr)
|
||||
{
|
||||
if ((u32)addr == addr)
|
||||
{
|
||||
if (addr < RAW_SPU_BASE_ADDR || (addr % RAW_SPU_OFFSET) < RAW_SPU_PROB_OFFSET || !RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET])
|
||||
{
|
||||
return re32(*(u32*)((u64)GetBaseAddr() + addr));
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 res;
|
||||
RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET]->Read32(addr, &res);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr);
|
||||
Emu.Pause();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
u64 MemoryBase::Read64(u64 addr)
|
||||
{
|
||||
if ((u32)addr == addr)
|
||||
{
|
||||
return re64(*(u64*)((u64)GetBaseAddr() + addr));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr);
|
||||
Emu.Pause();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
u128 MemoryBase::Read128(u64 addr)
|
||||
{
|
||||
if ((u32)addr == addr)
|
||||
{
|
||||
return re128(*(u128*)((u64)GetBaseAddr() + addr));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr);
|
||||
Emu.Pause();
|
||||
return u128::From128(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// MemoryBase
|
||||
template<> __forceinline u64 MemoryBase::ReverseData<1>(u64 val) { return val; }
|
||||
template<> __forceinline u64 MemoryBase::ReverseData<2>(u64 val) { return Reverse16(val); }
|
||||
template<> __forceinline u64 MemoryBase::ReverseData<4>(u64 val) { return Reverse32(val); }
|
||||
|
|
|
@ -52,20 +52,43 @@ public:
|
|||
MemoryBlock* RawSPUMem[(0x100000000 - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET];
|
||||
VirtualMemoryBlock RSXIOMem;
|
||||
|
||||
struct
|
||||
struct Wrapper32LE
|
||||
{
|
||||
private:
|
||||
void* m_base_addr;
|
||||
|
||||
public:
|
||||
Wrapper32LE() : m_base_addr(nullptr) {}
|
||||
|
||||
void Write8(const u32 addr, const u8 data) { *(u8*)((u8*)m_base_addr + addr) = data; }
|
||||
void Write16(const u32 addr, const u16 data) { *(u16*)((u8*)m_base_addr + addr) = data; }
|
||||
void Write32(const u32 addr, const u32 data) { *(u32*)((u8*)m_base_addr + addr) = data; }
|
||||
void Write64(const u32 addr, const u64 data) { *(u64*)((u8*)m_base_addr + addr) = data; }
|
||||
void Write128(const u32 addr, const u128 data) { *(u128*)((u8*)m_base_addr + addr) = data; }
|
||||
|
||||
u8 Read8(const u32 addr) { return *(u8*)((u8*)m_base_addr + addr); }
|
||||
u16 Read16(const u32 addr) { return *(u16*)((u8*)m_base_addr + addr); }
|
||||
u32 Read32(const u32 addr) { return *(u32*)((u8*)m_base_addr + addr); }
|
||||
u64 Read64(const u32 addr) { return *(u64*)((u8*)m_base_addr + addr); }
|
||||
u128 Read128(const u32 addr) { return *(u128*)((u8*)m_base_addr + addr); }
|
||||
|
||||
void Init(void* real_addr) { m_base_addr = real_addr; }
|
||||
};
|
||||
|
||||
struct : Wrapper32LE
|
||||
{
|
||||
DynamicMemoryBlockLE RAM;
|
||||
DynamicMemoryBlockLE Userspace;
|
||||
} PSVMemory;
|
||||
} PSV;
|
||||
|
||||
struct
|
||||
struct : Wrapper32LE
|
||||
{
|
||||
DynamicMemoryBlockLE Scratchpad;
|
||||
DynamicMemoryBlockLE VRAM;
|
||||
DynamicMemoryBlockLE RAM;
|
||||
DynamicMemoryBlockLE Kernel;
|
||||
DynamicMemoryBlockLE Userspace;
|
||||
} PSPMemory;
|
||||
} PSP;
|
||||
|
||||
bool m_inited;
|
||||
|
||||
|
@ -84,17 +107,26 @@ public:
|
|||
return m_base_addr;
|
||||
}
|
||||
|
||||
noinline void InvalidAddress(const char* func, const u64 addr)
|
||||
{
|
||||
LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", func, addr);
|
||||
}
|
||||
|
||||
void RegisterPages(u64 addr, u32 size)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||
|
||||
//LOG_NOTICE(MEMORY, "RegisterPages(addr=0x%llx, size=0x%x)", addr, size);
|
||||
for (u32 i = addr / 4096; i < (addr + size) / 4096; i++)
|
||||
for (u64 i = addr / 4096; i < (addr + size) / 4096; i++)
|
||||
{
|
||||
if (i >= sizeof(m_pages) / sizeof(m_pages[0])) break;
|
||||
if (i >= sizeof(m_pages) / sizeof(m_pages[0]))
|
||||
{
|
||||
InvalidAddress(__FUNCTION__, i * 4096);
|
||||
break;
|
||||
}
|
||||
if (m_pages[i])
|
||||
{
|
||||
LOG_ERROR(MEMORY, "Page already registered (page=0x%x)", i * 4096);
|
||||
LOG_ERROR(MEMORY, "Page already registered (addr=0x%llx)", i * 4096);
|
||||
}
|
||||
m_pages[i] = 1; // TODO: define page parameters
|
||||
}
|
||||
|
@ -105,12 +137,16 @@ public:
|
|||
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||
|
||||
//LOG_NOTICE(MEMORY, "UnregisterPages(addr=0x%llx, size=0x%x)", addr, size);
|
||||
for (u32 i = addr / 4096; i < (addr + size) / 4096; i++)
|
||||
for (u64 i = addr / 4096; i < (addr + size) / 4096; i++)
|
||||
{
|
||||
if (i >= sizeof(m_pages) / sizeof(m_pages[0])) break;
|
||||
if (i >= sizeof(m_pages) / sizeof(m_pages[0]))
|
||||
{
|
||||
InvalidAddress(__FUNCTION__, i * 4096);
|
||||
break;
|
||||
}
|
||||
if (!m_pages[i])
|
||||
{
|
||||
LOG_ERROR(MEMORY, "Page not registered (page=0x%x)", i * 4096);
|
||||
LOG_ERROR(MEMORY, "Page not registered (addr=0x%llx)", i * 4096);
|
||||
}
|
||||
m_pages[i] = 0; // TODO: define page parameters
|
||||
}
|
||||
|
@ -146,17 +182,25 @@ public:
|
|||
return (T)ReverseData<sizeof(T)>(val);
|
||||
};
|
||||
|
||||
u8* GetMemFromAddr(const u64 addr)
|
||||
template<typename T> u8* GetMemFromAddr(const T addr)
|
||||
{
|
||||
return (u8*)GetBaseAddr() + addr;
|
||||
if ((u32)addr == addr)
|
||||
{
|
||||
return (u8*)GetBaseAddr() + addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
InvalidAddress(__FUNCTION__, addr);
|
||||
return (u8*)GetBaseAddr();
|
||||
}
|
||||
}
|
||||
|
||||
void* VirtualToRealAddr(const u64 vaddr)
|
||||
template<typename T> void* VirtualToRealAddr(const T vaddr)
|
||||
{
|
||||
return GetMemFromAddr(vaddr);
|
||||
return GetMemFromAddr<T>(vaddr);
|
||||
}
|
||||
|
||||
u64 RealToVirtualAddr(const void* addr)
|
||||
u32 RealToVirtualAddr(const void* addr)
|
||||
{
|
||||
const u64 res = (u64)addr - (u64)GetBaseAddr();
|
||||
|
||||
|
@ -233,25 +277,27 @@ public:
|
|||
break;
|
||||
|
||||
case Memory_PSV:
|
||||
MemoryBlocks.push_back(PSVMemory.RAM.SetRange(0x81000000, 0x10000000));
|
||||
MemoryBlocks.push_back(UserMemory = PSVMemory.Userspace.SetRange(0x91000000, 0x10000000));
|
||||
MemoryBlocks.push_back(PSV.RAM.SetRange(0x81000000, 0x10000000));
|
||||
MemoryBlocks.push_back(UserMemory = PSV.Userspace.SetRange(0x91000000, 0x10000000));
|
||||
PSV.Init(GetBaseAddr());
|
||||
break;
|
||||
|
||||
case Memory_PSP:
|
||||
MemoryBlocks.push_back(PSPMemory.Scratchpad.SetRange(0x00010000, 0x00004000));
|
||||
MemoryBlocks.push_back(PSPMemory.VRAM.SetRange(0x04000000, 0x00200000));
|
||||
MemoryBlocks.push_back(PSPMemory.RAM.SetRange(0x08000000, 0x02000000));
|
||||
MemoryBlocks.push_back(PSPMemory.Kernel.SetRange(0x88000000, 0x00800000));
|
||||
MemoryBlocks.push_back(UserMemory = PSPMemory.Userspace.SetRange(0x08800000, 0x01800000));
|
||||
MemoryBlocks.push_back(PSP.Scratchpad.SetRange(0x00010000, 0x00004000));
|
||||
MemoryBlocks.push_back(PSP.VRAM.SetRange(0x04000000, 0x00200000));
|
||||
MemoryBlocks.push_back(PSP.RAM.SetRange(0x08000000, 0x02000000));
|
||||
MemoryBlocks.push_back(PSP.Kernel.SetRange(0x88000000, 0x00800000));
|
||||
MemoryBlocks.push_back(UserMemory = PSP.Userspace.SetRange(0x08800000, 0x01800000));
|
||||
PSP.Init(GetBaseAddr());
|
||||
break;
|
||||
}
|
||||
|
||||
LOG_NOTICE(MEMORY, "Memory initialized.");
|
||||
}
|
||||
|
||||
bool IsGoodAddr(const u64 addr)
|
||||
template<typename T> bool IsGoodAddr(const T addr)
|
||||
{
|
||||
if (addr >= 0x100000000 || !m_pages[addr / 4096]) // TODO: define page parameters
|
||||
if ((u32)addr != addr || !m_pages[addr / 4096]) // TODO: define page parameters
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -261,9 +307,9 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
bool IsGoodAddr(const u64 addr, const u32 size)
|
||||
template<typename T> bool IsGoodAddr(const T addr, const u32 size)
|
||||
{
|
||||
if (addr + size > 0x100000000)
|
||||
if ((u32)addr != addr || (u64)addr + (u64)size > 0x100000000ull)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -308,23 +354,152 @@ public:
|
|||
#endif
|
||||
}
|
||||
|
||||
void Write8(const u64 addr, const u8 data);
|
||||
void Write16(const u64 addr, const u16 data);
|
||||
void Write32(const u64 addr, const u32 data);
|
||||
void Write64(const u64 addr, const u64 data);
|
||||
void Write128(const u64 addr, const u128 data);
|
||||
//MemoryBase
|
||||
template<typename T> void Write8(T addr, const u8 data)
|
||||
{
|
||||
if ((u32)addr == addr)
|
||||
{
|
||||
*(u8*)((u8*)GetBaseAddr() + addr) = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
InvalidAddress(__FUNCTION__, addr);
|
||||
*(u8*)GetBaseAddr() = data;
|
||||
}
|
||||
}
|
||||
|
||||
bool Write8NN(const u64 addr, const u8 data);
|
||||
bool Write16NN(const u64 addr, const u16 data);
|
||||
bool Write32NN(const u64 addr, const u32 data);
|
||||
bool Write64NN(const u64 addr, const u64 data);
|
||||
bool Write128NN(const u64 addr, const u128 data);
|
||||
template<typename T> void Write16(T addr, const u16 data)
|
||||
{
|
||||
if ((u32)addr == addr)
|
||||
{
|
||||
*(u16*)((u8*)GetBaseAddr() + addr) = re16(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
InvalidAddress(__FUNCTION__, addr);
|
||||
*(u16*)GetBaseAddr() = data;
|
||||
}
|
||||
}
|
||||
|
||||
u8 Read8(const u64 addr);
|
||||
u16 Read16(const u64 addr);
|
||||
u32 Read32(const u64 addr);
|
||||
u64 Read64(const u64 addr);
|
||||
u128 Read128(const u64 addr);
|
||||
template<typename T> void Write32(T addr, const u32 data)
|
||||
{
|
||||
if ((u32)addr == addr)
|
||||
{
|
||||
if (addr < RAW_SPU_BASE_ADDR || (addr % RAW_SPU_OFFSET) < RAW_SPU_PROB_OFFSET || !RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET])
|
||||
{
|
||||
*(u32*)((u8*)GetBaseAddr() + addr) = re32(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET]->Write32(addr, data);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
InvalidAddress(__FUNCTION__, addr);
|
||||
*(u32*)GetBaseAddr() = data;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> void Write64(T addr, const u64 data)
|
||||
{
|
||||
if ((u32)addr == addr)
|
||||
{
|
||||
*(u64*)((u8*)GetBaseAddr() + addr) = re64(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
InvalidAddress(__FUNCTION__, addr);
|
||||
*(u64*)GetBaseAddr() = data;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> void Write128(T addr, const u128 data)
|
||||
{
|
||||
if ((u32)addr == addr)
|
||||
{
|
||||
*(u128*)((u8*)GetBaseAddr() + addr) = re128(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
InvalidAddress(__FUNCTION__, addr);
|
||||
*(u128*)GetBaseAddr() = data;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> u8 Read8(T addr)
|
||||
{
|
||||
if ((u32)addr == addr)
|
||||
{
|
||||
return *(u8*)((u8*)GetBaseAddr() + addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
InvalidAddress(__FUNCTION__, addr);
|
||||
return *(u8*)GetBaseAddr();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> u16 Read16(T addr)
|
||||
{
|
||||
if ((u32)addr == addr)
|
||||
{
|
||||
return re16(*(u16*)((u8*)GetBaseAddr() + addr));
|
||||
}
|
||||
else
|
||||
{
|
||||
InvalidAddress(__FUNCTION__, addr);
|
||||
return *(u16*)GetBaseAddr();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> u32 Read32(T addr)
|
||||
{
|
||||
if ((u32)addr == addr)
|
||||
{
|
||||
if (addr < RAW_SPU_BASE_ADDR || (addr % RAW_SPU_OFFSET) < RAW_SPU_PROB_OFFSET || !RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET])
|
||||
{
|
||||
return re32(*(u32*)((u8*)GetBaseAddr() + addr));
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 res;
|
||||
RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET]->Read32(addr, &res);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
InvalidAddress(__FUNCTION__, addr);
|
||||
return *(u32*)GetBaseAddr();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> u64 Read64(T addr)
|
||||
{
|
||||
if ((u32)addr == addr)
|
||||
{
|
||||
return re64(*(u64*)((u8*)GetBaseAddr() + addr));
|
||||
}
|
||||
else
|
||||
{
|
||||
InvalidAddress(__FUNCTION__, addr);
|
||||
return *(u64*)GetBaseAddr();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> u128 Read128(T addr)
|
||||
{
|
||||
if ((u32)addr == addr)
|
||||
{
|
||||
return re128(*(u128*)((u8*)GetBaseAddr() + addr));
|
||||
}
|
||||
else
|
||||
{
|
||||
InvalidAddress(__FUNCTION__, addr);
|
||||
return *(u128*)GetBaseAddr();
|
||||
}
|
||||
}
|
||||
|
||||
bool CopyToReal(void* real, u64 from, u32 count)
|
||||
{
|
||||
|
@ -469,13 +644,13 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
u8* operator + (const u64 vaddr)
|
||||
template<typename T> u8* operator + (const T vaddr)
|
||||
{
|
||||
u8* ret = GetMemFromAddr(vaddr);
|
||||
u8* ret = GetMemFromAddr<T>(vaddr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
u8& operator[] (const u64 vaddr)
|
||||
template<typename T> u8& operator[] (const T vaddr)
|
||||
{
|
||||
return *(*this + vaddr);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "Emu/System.h"
|
||||
#include "Callback.h"
|
||||
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "Emu/Cell/PPCThread.h"
|
||||
|
||||
Callback::Callback(u32 slot, u64 addr)
|
||||
|
@ -13,6 +14,7 @@ Callback::Callback(u32 slot, u64 addr)
|
|||
, a2(0)
|
||||
, a3(0)
|
||||
, a4(0)
|
||||
, a5(0)
|
||||
, m_has_data(false)
|
||||
, m_name("Callback")
|
||||
{
|
||||
|
@ -43,12 +45,13 @@ bool Callback::HasData() const
|
|||
return m_has_data;
|
||||
}
|
||||
|
||||
void Callback::Handle(u64 _a1, u64 _a2, u64 _a3, u64 _a4)
|
||||
void Callback::Handle(u64 _a1, u64 _a2, u64 _a3, u64 _a4, u64 _a5)
|
||||
{
|
||||
a1 = _a1;
|
||||
a2 = _a2;
|
||||
a3 = _a3;
|
||||
a4 = _a4;
|
||||
a5 = _a5;
|
||||
m_has_data = true;
|
||||
}
|
||||
|
||||
|
@ -97,6 +100,7 @@ again:
|
|||
thr.SetArg(2, a3);
|
||||
thr.SetArg(3, a4);
|
||||
thr.Run();
|
||||
((PPUThread&)thr).GPR[7] = a5;
|
||||
|
||||
thr.Exec();
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ public:
|
|||
u64 a2;
|
||||
u64 a3;
|
||||
u64 a4;
|
||||
u64 a5;
|
||||
|
||||
u32 GetSlot() const;
|
||||
u64 GetAddr() const;
|
||||
|
@ -23,7 +24,7 @@ public:
|
|||
bool HasData() const;
|
||||
|
||||
Callback(u32 slot = 0, u64 addr = 0);
|
||||
void Handle(u64 a1 = 0, u64 a2 = 0, u64 a3 = 0, u64 a4 = 0);
|
||||
void Handle(u64 a1 = 0, u64 a2 = 0, u64 a3 = 0, u64 a4 = 0, u64 a5 = 0);
|
||||
u64 Branch(bool wait);
|
||||
void SetName(const std::string& name);
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ int UTF16stoUTF8s(mem16_ptr_t utf16, mem64_t utf16_len, mem8_ptr_t utf8, mem64_t
|
|||
if (!utf16.IsGood() || !utf16_len.IsGood() || !utf8_len.IsGood())
|
||||
return SRCIllegal;
|
||||
|
||||
std::u16string wstr =(char16_t*)Memory.VirtualToRealAddr(utf16);
|
||||
std::u16string wstr =(char16_t*)Memory.VirtualToRealAddr(utf16.GetAddr());
|
||||
wstr.resize(utf16_len.GetValue()); // TODO: Is this really the role of utf16_len in this function?
|
||||
#ifdef _MSC_VER
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert;
|
||||
|
|
|
@ -361,7 +361,7 @@ int cellSurMixerCreate(const mem_ptr_t<CellSurMixerConfig> config)
|
|||
break;
|
||||
}
|
||||
|
||||
if (mixcount > (port.tag + 14)) // preemptive buffer filling (probably hack)
|
||||
if (mixcount > (port.tag + 0)) // adding positive value (1-15): preemptive buffer filling (hack)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
continue;
|
||||
|
@ -531,7 +531,8 @@ int cellSurMixerStart()
|
|||
|
||||
int cellSurMixerSetParameter(u32 param, float value)
|
||||
{
|
||||
libmixer->Error("cellSurMixerSetParameter(param=0x%x, value=%f)", param, value);
|
||||
declCPU();
|
||||
libmixer->Error("cellSurMixerSetParameter(param=0x%x, value=%f, FPR[1]=%f, FPR[2]=%f)", param, value, (float&)CPU.FPR[1], (float&)CPU.FPR[2]);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -559,8 +560,7 @@ int cellSurMixerSurBusAddData(u32 busNo, u32 offset, u32 addr, u32 samples)
|
|||
}
|
||||
else
|
||||
{
|
||||
libmixer->Error("cellSurMixerSurBusAddData(busNo=%d, offset=0x%x, addr=0x%x, samples=%d)", busNo, offset, addr, samples);
|
||||
Emu.Pause();
|
||||
libmixer->Error("cellSurMixerSurBusAddData(busNo=%d, offset=0x%x, addr=0x%x, samples=%d): unknown parameters", busNo, offset, addr, samples);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -205,20 +205,19 @@ s32 sys_ppu_thread_create(mem64_t thread_id, u32 entry, u64 arg, s32 prio, u32 s
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
void sys_ppu_thread_once(u32 once_ctrl_addr, u32 entry)
|
||||
void sys_ppu_thread_once(mem_ptr_t<std::atomic<be_t<u32>>> once_ctrl, u32 entry)
|
||||
{
|
||||
sysPrxForUser->Warning("sys_ppu_thread_once(once_ctrl_addr=0x%x, entry=0x%x)", once_ctrl_addr, entry);
|
||||
sysPrxForUser->Warning("sys_ppu_thread_once(once_ctrl_addr=0x%x, entry=0x%x)", once_ctrl.GetAddr(), entry);
|
||||
|
||||
if(Memory.IsGoodAddr(once_ctrl_addr, 4) && Memory.Read32(once_ctrl_addr) == SYS_PPU_THREAD_ONCE_INIT)
|
||||
be_t<u32> old = SYS_PPU_THREAD_ONCE_INIT;
|
||||
if (once_ctrl->compare_exchange_weak(old, SYS_PPU_THREAD_DONE_INIT))
|
||||
{
|
||||
Memory.Write32(once_ctrl_addr, SYS_PPU_THREAD_DONE_INIT);
|
||||
|
||||
CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU);
|
||||
new_thread.SetEntry(entry);
|
||||
new_thread.Run();
|
||||
new_thread.Exec();
|
||||
|
||||
//GetCurrentPPUThread().Wait(new_thread);
|
||||
while (new_thread.IsAlive()) SM_Sleep();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,5 +24,5 @@ s32 sys_ppu_thread_get_stack_information(u32 info_addr);
|
|||
s32 sys_ppu_thread_stop(u64 thread_id);
|
||||
s32 sys_ppu_thread_restart(u64 thread_id);
|
||||
s32 sys_ppu_thread_create(mem64_t thread_id, u32 entry, u64 arg, s32 prio, u32 stacksize, u64 flags, u32 threadname_addr);
|
||||
void sys_ppu_thread_once(u32 once_ctrl_addr, u32 entry);
|
||||
void sys_ppu_thread_once(mem_ptr_t<std::atomic<be_t<u32>>> once_ctrl, u32 entry);
|
||||
s32 sys_ppu_thread_get_id(const u32 id_addr);
|
||||
|
|
|
@ -597,7 +597,7 @@ s32 sys_spu_thread_connect_event(u32 id, u32 eq_id, u32 et, u8 spup)
|
|||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
// TODO: check if can receive this events
|
||||
// TODO: check if can receive these events
|
||||
|
||||
SPUThread& spu = *(SPUThread*)thr;
|
||||
|
||||
|
@ -706,51 +706,82 @@ s32 sys_spu_thread_unbind_queue(u32 id, u32 spuq_num)
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, u32 spup_addr)
|
||||
s32 sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq_id, u64 req, mem8_t spup)
|
||||
{
|
||||
sc_spu.Error("sys_spu_thread_group_connect_event_all_threads(id=%d, eq=%d, req=0x%llx, spup_addr=0x%x)",
|
||||
id, eq, req, spup_addr);
|
||||
sc_spu.Warning("sys_spu_thread_group_connect_event_all_threads(id=%d, eq_id=%d, req=0x%llx, spup_addr=0x%x)",
|
||||
id, eq_id, req, spup.GetAddr());
|
||||
|
||||
EventQueue* equeue;
|
||||
if(!sys_event.CheckId(eq, equeue))
|
||||
if (!spup.IsGood())
|
||||
{
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
EventQueue* eq;
|
||||
if (!Emu.GetIdManager().GetIDData(eq_id, eq))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if(!req)
|
||||
if (!req)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
SpuGroupInfo* group;
|
||||
if(!Emu.GetIdManager().GetIDData(id, group))
|
||||
if (!Emu.GetIdManager().GetIDData(id, group))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
/*
|
||||
for(u32 i=0; i<group->list.size(); ++i)
|
||||
|
||||
std::vector<SPUThread*> threads;
|
||||
for (auto& v : group->list)
|
||||
{
|
||||
CPUThread* t;
|
||||
if(t = Emu.GetCPU().GetThread(group->list[i]))
|
||||
if (!v) continue;
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(v);
|
||||
if (thr->GetType() != CPU_THREAD_SPU)
|
||||
{
|
||||
bool finded_port = false;
|
||||
for(int j=0; j<equeue->pos; ++j)
|
||||
sc_spu.Error("sys_spu_thread_group_connect_event_all_threads(): CELL_ESTAT (wrong thread type)");
|
||||
return CELL_ESTAT;
|
||||
}
|
||||
threads.push_back((SPUThread*)thr);
|
||||
}
|
||||
|
||||
if (threads.size() != group->m_count)
|
||||
{
|
||||
sc_spu.Error("sys_spu_thread_group_connect_event_all_threads(): CELL_ESTAT (%d from %d)", (u32)threads.size(), group->m_count);
|
||||
return CELL_ESTAT;
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < 64; i++) // port number
|
||||
{
|
||||
bool found = true;
|
||||
if (req & (1ull << i))
|
||||
{
|
||||
for (auto& t : threads) t->SPUPs[i].m_mutex.lock();
|
||||
|
||||
for (auto& t : threads) if (t->SPUPs[i].eq) found = false;
|
||||
|
||||
if (found)
|
||||
{
|
||||
if(!equeue->ports[j]->thread)
|
||||
for (auto& t : threads)
|
||||
{
|
||||
finded_port = true;
|
||||
equeue->ports[j]->thread = t;
|
||||
eq->ports.add(&(t->SPUPs[i]));
|
||||
t->SPUPs[i].eq = eq;
|
||||
}
|
||||
spup = (u8)i;
|
||||
}
|
||||
|
||||
if(!finded_port)
|
||||
{
|
||||
return CELL_EISCONN;
|
||||
}
|
||||
for (auto& t : threads) t->SPUPs[i].m_mutex.unlock();
|
||||
}
|
||||
}*/
|
||||
return CELL_OK;
|
||||
else
|
||||
{
|
||||
found = false;
|
||||
}
|
||||
|
||||
if (found) return CELL_OK;
|
||||
}
|
||||
|
||||
return CELL_EISCONN;
|
||||
}
|
||||
|
||||
s32 sys_spu_thread_group_disconnect_event_all_threads(u32 id, u8 spup)
|
||||
|
|
|
@ -64,6 +64,7 @@ struct SpuGroupInfo
|
|||
int m_prio;
|
||||
int m_type;
|
||||
int m_ct;
|
||||
u32 m_count;
|
||||
|
||||
SpuGroupInfo(const std::string& name, u32 num, int prio, int type, u32 ct)
|
||||
: m_name(name)
|
||||
|
@ -71,13 +72,10 @@ struct SpuGroupInfo
|
|||
, m_type(type)
|
||||
, m_ct(ct)
|
||||
, lock(0)
|
||||
, m_count(num)
|
||||
{
|
||||
num = 256;
|
||||
list.resize(num);
|
||||
for (u32 i = 0; i < num; i++)
|
||||
{
|
||||
list[i] = 0;
|
||||
}
|
||||
list.resize(256);
|
||||
for (auto& v : list) v = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -95,7 +93,7 @@ s32 sys_spu_thread_create(mem32_t thread_id, mem32_t entry, u64 arg, int prio, u
|
|||
s32 sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status);
|
||||
s32 sys_spu_thread_group_connect_event(u32 id, u32 eq, u32 et);
|
||||
s32 sys_spu_thread_group_disconnect_event(u32 id, u32 et);
|
||||
s32 sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, u32 spup_addr);
|
||||
s32 sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq_id, u64 req, mem8_t spup);
|
||||
s32 sys_spu_thread_group_disconnect_event_all_threads(u32 id, u8 spup);
|
||||
s32 sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type);
|
||||
s32 sys_spu_thread_read_ls(u32 id, u32 address, mem64_t value, u32 type);
|
||||
|
|
|
@ -103,8 +103,16 @@ s32 sys_timer_disconnect_event_queue(u32 timer_id)
|
|||
|
||||
s32 sys_timer_sleep(u32 sleep_time)
|
||||
{
|
||||
sys_timer.Warning("sys_timer_sleep(sleep_time=%d)", sleep_time);
|
||||
std::this_thread::sleep_for(std::chrono::seconds(sleep_time));
|
||||
sys_timer.Log("sys_timer_sleep(sleep_time=%d)", sleep_time);
|
||||
for (u32 i = 0; i < sleep_time; i++)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
sys_timer.Warning("sys_timer_sleep(sleep_time=%d) aborted", sleep_time);
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -112,6 +120,15 @@ s32 sys_timer_usleep(u64 sleep_time)
|
|||
{
|
||||
sys_timer.Log("sys_timer_usleep(sleep_time=%lld)", sleep_time);
|
||||
if (sleep_time > 0xFFFFFFFFFFFF) sleep_time = 0xFFFFFFFFFFFF; //2^48-1
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(sleep_time));
|
||||
for (u32 i = 0; i < sleep_time / 1000000; i++)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
sys_timer.Warning("sys_timer_usleep(sleep_time=%lld) aborted", sleep_time);
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(sleep_time % 1000000));
|
||||
return CELL_OK;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ s32 sys_tty_read(u32 ch, u64 buf_addr, u32 len, u64 preadlen_addr)
|
|||
{
|
||||
// We currently do not support reading from the Console
|
||||
LOG_WARNING(HLE, "sys_tty_read: ch: %d, buf addr: %llx, len: %d", ch, buf_addr, len);
|
||||
Memory.Write32NN(preadlen_addr, len);
|
||||
Memory.Write32(preadlen_addr, len);
|
||||
Emu.Pause();
|
||||
|
||||
return CELL_OK;
|
||||
|
|
|
@ -237,8 +237,8 @@ bool ELF32Loader::LoadPhdrData(u64 _offset)
|
|||
switch(machine)
|
||||
{
|
||||
case MACHINE_SPU: break;
|
||||
case MACHINE_MIPS: Memory.PSPMemory.RAM.AllocFixed(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); break;
|
||||
case MACHINE_ARM: Memory.PSVMemory.RAM.AllocFixed(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); break;
|
||||
case MACHINE_MIPS: Memory.PSP.RAM.AllocFixed(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); break;
|
||||
case MACHINE_ARM: Memory.PSV.RAM.AllocFixed(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
|
|
Loading…
Add table
Reference in a new issue