mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-06 15:01:28 +12:00
ThreadBase rewritten (wip)
This commit is contained in:
parent
b7a320fbbd
commit
3aefa2b4e1
85 changed files with 1960 additions and 2183 deletions
|
@ -3,6 +3,7 @@
|
|||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
|
@ -489,47 +490,39 @@ void fill_ppu_exec_map(u32 addr, u32 size)
|
|||
}
|
||||
}
|
||||
|
||||
PPUThread::PPUThread() : CPUThread(CPU_THREAD_PPU)
|
||||
PPUThread::PPUThread(const std::string& name)
|
||||
: CPUThread(CPU_THREAD_PPU, name, [this]{ return fmt::format("%s[0x%x] Thread (%s)[0x%08x]", GetTypeString(), GetId(), GetName(), PC); })
|
||||
{
|
||||
Reset();
|
||||
InitRotateMask();
|
||||
}
|
||||
|
||||
PPUThread::~PPUThread()
|
||||
{
|
||||
ppu_free_tls(GetId());
|
||||
cv.notify_one();
|
||||
join();
|
||||
|
||||
ppu_free_tls(m_id);
|
||||
}
|
||||
|
||||
void PPUThread::DoReset()
|
||||
void PPUThread::DumpInformation() const
|
||||
{
|
||||
//reset regs
|
||||
memset(VPR, 0, sizeof(VPR));
|
||||
memset(FPR, 0, sizeof(FPR));
|
||||
memset(GPR, 0, sizeof(GPR));
|
||||
memset(SPRG, 0, sizeof(SPRG));
|
||||
if (hle_code < 0)
|
||||
{
|
||||
LOG_SUCCESS(HLE, "Information: syscall %lld (%s)", ~hle_code, SysCalls::GetFuncName(hle_code));
|
||||
}
|
||||
|
||||
CR.CR = 0;
|
||||
LR = 0;
|
||||
CTR = 0;
|
||||
TB = 0;
|
||||
XER.XER = 0;
|
||||
FPSCR.FPSCR = 0;
|
||||
VSCR.VSCR = 0;
|
||||
VRSAVE = 0;
|
||||
if (hle_code > 0)
|
||||
{
|
||||
LOG_SUCCESS(HLE, "Information: function 0x%llx (%s)", hle_code, SysCalls::GetFuncName(hle_code));
|
||||
}
|
||||
|
||||
CPUThread::DumpInformation();
|
||||
}
|
||||
|
||||
void PPUThread::InitRegs()
|
||||
{
|
||||
const u32 pc = entry ? vm::read32(entry).value() : 0;
|
||||
const u32 rtoc = entry ? vm::read32(entry + 4).value() : 0;
|
||||
|
||||
SetPc(pc);
|
||||
|
||||
GPR[1] = align(m_stack_addr + m_stack_size, 0x200) - 0x200;
|
||||
GPR[2] = rtoc;
|
||||
//GPR[11] = entry;
|
||||
//GPR[12] = Emu.GetMallocPageSize();
|
||||
GPR[13] = ppu_get_tls(GetId()) + 0x7000; // 0x7000 is usually subtracted from r13 to access first TLS element (details are not clear)
|
||||
GPR[1] = align(stack_addr + stack_size, 0x200) - 0x200;
|
||||
GPR[13] = ppu_get_tls(m_id) + 0x7000; // 0x7000 is subtracted from r13 to access first TLS element
|
||||
|
||||
LR = 0;
|
||||
CTR = PC;
|
||||
|
@ -540,32 +533,40 @@ void PPUThread::InitRegs()
|
|||
|
||||
void PPUThread::InitStack()
|
||||
{
|
||||
if (!m_stack_addr)
|
||||
if (!stack_addr)
|
||||
{
|
||||
assert(m_stack_size);
|
||||
m_stack_addr = Memory.StackMem.AllocAlign(m_stack_size, 4096);
|
||||
if (!stack_size)
|
||||
{
|
||||
throw EXCEPTION("Invalid stack size");
|
||||
}
|
||||
|
||||
stack_addr = Memory.StackMem.AllocAlign(stack_size, 4096);
|
||||
|
||||
if (!stack_addr)
|
||||
{
|
||||
throw EXCEPTION("Out of stack memory");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PPUThread::CloseStack()
|
||||
{
|
||||
if (m_stack_addr)
|
||||
if (stack_addr)
|
||||
{
|
||||
Memory.StackMem.Free(m_stack_addr);
|
||||
m_stack_addr = 0;
|
||||
Memory.StackMem.Free(stack_addr);
|
||||
stack_addr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void PPUThread::DoRun()
|
||||
{
|
||||
m_dec = nullptr;
|
||||
m_dec.reset();
|
||||
|
||||
switch (auto mode = Ini.CPUDecoderMode.GetValue())
|
||||
{
|
||||
case 0: // original interpreter
|
||||
{
|
||||
auto ppui = new PPUInterpreter(*this);
|
||||
m_dec = new PPUDecoder(ppui);
|
||||
m_dec.reset(new PPUDecoder(new PPUInterpreter(*this)));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -575,18 +576,18 @@ void PPUThread::DoRun()
|
|||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
#ifdef PPU_LLVM_RECOMPILER
|
||||
SetCallStackTracing(false);
|
||||
if (!m_dec) {
|
||||
m_dec = new ppu_recompiler_llvm::ExecutionEngine(*this);
|
||||
}
|
||||
m_dec.reset(new ppu_recompiler_llvm::ExecutionEngine(*this));
|
||||
#else
|
||||
LOG_ERROR(PPU, "This image does not include PPU JIT (LLVM)");
|
||||
Emu.Pause();
|
||||
#endif
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
//case 3: m_dec = new PPURecompiler(*this); break;
|
||||
//case 3: m_dec.reset(new PPURecompiler(*this)); break;
|
||||
|
||||
default:
|
||||
{
|
||||
|
@ -596,20 +597,6 @@ void PPUThread::DoRun()
|
|||
}
|
||||
}
|
||||
|
||||
void PPUThread::DoResume()
|
||||
{
|
||||
}
|
||||
|
||||
void PPUThread::DoPause()
|
||||
{
|
||||
}
|
||||
|
||||
void PPUThread::DoStop()
|
||||
{
|
||||
delete m_dec;
|
||||
m_dec = nullptr;
|
||||
}
|
||||
|
||||
bool FPRdouble::IsINF(PPCdouble d)
|
||||
{
|
||||
return ((u64&)d & 0x7FFFFFFFFFFFFFFFULL) == 0x7FF0000000000000ULL;
|
||||
|
@ -652,42 +639,45 @@ u64 PPUThread::GetStackArg(s32 i)
|
|||
|
||||
void PPUThread::FastCall2(u32 addr, u32 rtoc)
|
||||
{
|
||||
auto old_status = m_status;
|
||||
if (!is_current())
|
||||
{
|
||||
throw EXCEPTION("Called from the wrong thread");
|
||||
}
|
||||
|
||||
auto old_PC = PC;
|
||||
auto old_stack = GPR[1];
|
||||
auto old_rtoc = GPR[2];
|
||||
auto old_LR = LR;
|
||||
auto old_thread = GetCurrentNamedThread();
|
||||
auto old_task = decltype(custom_task)();
|
||||
|
||||
m_status = Running;
|
||||
PC = addr;
|
||||
GPR[2] = rtoc;
|
||||
LR = Emu.GetCPUThreadStop();
|
||||
SetCurrentNamedThread(this);
|
||||
custom_task.swap(old_task);
|
||||
|
||||
Task();
|
||||
try
|
||||
{
|
||||
Task();
|
||||
}
|
||||
catch (CPUThreadReturn)
|
||||
{
|
||||
}
|
||||
|
||||
m_status = old_status;
|
||||
PC = old_PC;
|
||||
|
||||
if (GPR[1] != old_stack && !Emu.IsStopped()) // GPR[1] shouldn't change
|
||||
if (GPR[1] != old_stack) // GPR[1] shouldn't change
|
||||
{
|
||||
LOG_ERROR(PPU, "PPUThread::FastCall2(0x%x,0x%x): stack inconsistency (SP=0x%llx, old=0x%llx)", addr, rtoc, GPR[1], old_stack);
|
||||
GPR[1] = old_stack;
|
||||
throw EXCEPTION("Stack inconsistency (addr=0x%x, rtoc=0x%x, SP=0x%llx, old=0x%llx)", addr, rtoc, GPR[1], old_stack);
|
||||
}
|
||||
|
||||
GPR[2] = old_rtoc;
|
||||
LR = old_LR;
|
||||
SetCurrentNamedThread(old_thread);
|
||||
custom_task.swap(old_task);
|
||||
}
|
||||
|
||||
void PPUThread::FastStop()
|
||||
{
|
||||
m_status = Stopped;
|
||||
m_events |= CPU_EVENT_STOP;
|
||||
throw CPUThreadReturn{};
|
||||
}
|
||||
|
||||
void PPUThread::Task()
|
||||
|
@ -696,54 +686,59 @@ void PPUThread::Task()
|
|||
|
||||
if (custom_task)
|
||||
{
|
||||
if (CheckStatus()) return;
|
||||
|
||||
return custom_task(*this);
|
||||
}
|
||||
|
||||
if (m_dec)
|
||||
{
|
||||
return CPUThread::Task();
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
// get interpreter function
|
||||
const auto func = g_ppu_inter_func_list[*(u32*)((u8*)g_ppu_exec_map + PC)];
|
||||
|
||||
if (m_events)
|
||||
while (true)
|
||||
{
|
||||
// process events
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (m_state.load() && CheckStatus()) return;
|
||||
|
||||
if (m_events & CPU_EVENT_STOP && (IsStopped() || IsPaused()))
|
||||
{
|
||||
m_events &= ~CPU_EVENT_STOP;
|
||||
return;
|
||||
}
|
||||
// decode instruction using specified decoder
|
||||
m_dec->DecodeMemory(PC);
|
||||
|
||||
// next instruction
|
||||
PC += 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (m_state.load() && CheckStatus()) return;
|
||||
|
||||
// read opcode
|
||||
const ppu_opcode_t opcode = { vm::read32(PC) };
|
||||
// get interpreter function
|
||||
const auto func = g_ppu_inter_func_list[*(u32*)((u8*)g_ppu_exec_map + PC)];
|
||||
|
||||
// call interpreter function
|
||||
func(*this, opcode);
|
||||
// read opcode
|
||||
const ppu_opcode_t opcode = { vm::read32(PC) };
|
||||
|
||||
// next instruction
|
||||
//PC += 4;
|
||||
NextPc(4);
|
||||
// call interpreter function
|
||||
func(*this, opcode);
|
||||
|
||||
// next instruction
|
||||
PC += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ppu_thread::ppu_thread(u32 entry, const std::string& name, u32 stack_size, u32 prio)
|
||||
ppu_thread::ppu_thread(u32 entry, const std::string& name, u32 stack_size, s32 prio)
|
||||
{
|
||||
thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU);
|
||||
auto ppu = Emu.GetIdManager().make_ptr<PPUThread>(name);
|
||||
|
||||
thread->SetName(name);
|
||||
thread->SetEntry(entry);
|
||||
thread->SetStackSize(stack_size ? stack_size : Emu.GetPrimaryStackSize());
|
||||
thread->SetPrio(prio ? prio : Emu.GetPrimaryPrio());
|
||||
if (entry)
|
||||
{
|
||||
ppu->PC = vm::read32(entry);
|
||||
ppu->GPR[2] = vm::read32(entry + 4); // rtoc
|
||||
}
|
||||
|
||||
ppu->stack_size = stack_size ? stack_size : Emu.GetPrimaryStackSize();
|
||||
ppu->prio = prio ? prio : Emu.GetPrimaryPrio();
|
||||
|
||||
thread = std::move(ppu);
|
||||
|
||||
argc = 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue