#include "stdafx.h" #include "rpcs3/Ini.h" #include "Utilities/Log.h" #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/Cell/PPUThread.h" #include "Emu/SysCalls/SysCalls.h" #include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Static.h" #include "Emu/Cell/PPUDecoder.h" #include "Emu/Cell/PPUInterpreter.h" PPUThread& GetCurrentPPUThread() { PPCThread* thread = GetCurrentPPCThread(); if(!thread || thread->GetType() != CPU_THREAD_PPU) throw std::string("GetCurrentPPUThread: bad thread"); return *(PPUThread*)thread; } PPUThread::PPUThread() : PPCThread(CPU_THREAD_PPU) { owned_mutexes = 0; Reset(); } PPUThread::~PPUThread() { } void PPUThread::DoReset() { PPCThread::DoReset(); //reset regs memset(VPR, 0, sizeof(VPR)); memset(FPR, 0, sizeof(FPR)); memset(GPR, 0, sizeof(GPR)); memset(SPRG, 0, sizeof(SPRG)); CR.CR = 0; LR = 0; CTR = 0; USPRG0 = 0; TB = 0; XER.XER = 0; FPSCR.FPSCR = 0; VSCR.VSCR = 0; cycle = 0; } void PPUThread::AddArgv(const std::string& arg) { m_stack_point -= arg.length() + 1; m_stack_point = AlignAddr(m_stack_point, 0x10) - 0x10; m_argv_addr.push_back(m_stack_point); Memory.WriteString(m_stack_point, arg); } void PPUThread::InitRegs() { const u32 pc = Memory.Read32(entry); const u32 rtoc = Memory.Read32(entry + 4); //ConLog.Write("entry = 0x%x", entry); //ConLog.Write("rtoc = 0x%x", rtoc); SetPc(pc); /* const s32 thread_num = Emu.GetCPU().GetThreadNumById(GetType(), GetId()); if(thread_num < 0) { LOG_ERROR(PPU, "GetThreadNumById failed."); Emu.Pause(); return; } */ /* const s32 tls_size = Emu.GetTLSFilesz() * thread_num; if(tls_size >= Emu.GetTLSMemsz()) { LOG_ERROR(PPU, "Out of TLS memory."); Emu.Pause(); return; } */ m_stack_point = AlignAddr(m_stack_point, 0x200) - 0x200; GPR[1] = m_stack_point; GPR[2] = rtoc; /* for(int i=4; i<32; ++i) { if(i != 6) GPR[i] = (i+1) * 0x10000; } */ if(m_argv_addr.size()) { u64 argc = m_argv_addr.size(); m_stack_point -= 0xc + 4 * argc; u64 argv = m_stack_point; mem64_ptr_t argv_list(argv); for(int i=0; i b) return CR_GT; if(a == b) return CR_EQ; return CR_SO; } u64 PPUThread::GetStackArg(s32 i) { return Memory.Read64(GPR[1] + 0x70 + 0x8 * (i - 9)); } u64 PPUThread::FastCall(u64 addr, u64 rtoc, u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7, u64 arg8) { GPR[3] = arg1; GPR[4] = arg2; GPR[5] = arg3; GPR[6] = arg4; GPR[7] = arg5; GPR[8] = arg6; GPR[9] = arg7; GPR[10] = arg8; return FastCall2(addr, rtoc); } u64 PPUThread::FastCall2(u64 addr, u64 rtoc) { auto old_status = m_status; auto old_PC = PC; auto old_rtoc = GPR[2]; auto old_LR = LR; auto old_thread = GetCurrentNamedThread(); m_status = Running; PC = addr; GPR[2] = rtoc; LR = Emu.m_ppu_thr_stop; SetCurrentNamedThread(this); Task(); m_status = old_status; PC = old_PC; GPR[2] = old_rtoc; LR = old_LR; SetCurrentNamedThread(old_thread); return GPR[3]; } void PPUThread::FastStop() { m_status = Stopped; }