Merge pull request #572 from Nekotekina/master

Update
This commit is contained in:
Alexandro Sánchez Bach 2014-07-15 01:06:53 +02:00
commit 75e81bc969
23 changed files with 439 additions and 334 deletions

View file

@ -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

@ -1 +1 @@
Subproject commit a66efd54609aab7dd98e34c069937f34aa7c8f95
Subproject commit 3363e4138b003be36dfb63cf8c63cf360f04276f

View file

@ -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>

View file

@ -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>

View file

@ -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
{

View file

@ -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;
}
}

View file

@ -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());
}

View file

@ -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)
{

View file

@ -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);

View file

@ -362,7 +362,7 @@ public:
void Init()
{
m_index = 0;
m_indval = 0;
}
__forceinline bool Pop(u32& res)

View file

@ -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); }

View file

@ -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);
}

View file

@ -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();

View file

@ -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);

View file

@ -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;

View file

@ -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;
}

View file

@ -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();
}
}

View file

@ -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);

View file

@ -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)

View file

@ -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);

View file

@ -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;
}

View file

@ -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;

View file

@ -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;