SPU: Make spu_thread::offset private

This commit is contained in:
Eladash 2020-07-17 11:18:04 +03:00 committed by Ivan
parent 6cc0fe4221
commit c37bc3c55c
14 changed files with 151 additions and 132 deletions

View File

@ -1417,7 +1417,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
{ {
const auto& spu = static_cast<spu_thread&>(*cpu); const auto& spu = static_cast<spu_thread&>(*cpu);
const u64 type = spu.offset < RAW_SPU_BASE_ADDR ? const u64 type = spu.get_type() == spu_type::threaded ?
SYS_MEMORY_PAGE_FAULT_TYPE_SPU_THREAD : SYS_MEMORY_PAGE_FAULT_TYPE_SPU_THREAD :
SYS_MEMORY_PAGE_FAULT_TYPE_RAW_SPU; SYS_MEMORY_PAGE_FAULT_TYPE_RAW_SPU;

View File

@ -87,7 +87,7 @@ void cellSpursModulePutTrace(CellSpursTracePacket* packet, u32 dmaTagId)
// Check for execution right requests // Check for execution right requests
u32 cellSpursModulePollStatus(spu_thread& spu, u32* status) u32 cellSpursModulePollStatus(spu_thread& spu, u32* status)
{ {
auto ctxt = vm::_ptr<SpursKernelContext>(spu.offset + 0x100); auto ctxt = spu._ptr<SpursKernelContext>(0x100);
spu.gpr[3]._u32[3] = 1; spu.gpr[3]._u32[3] = 1;
if (ctxt->spurs->flags1 & SF1_32_WORKLOADS) if (ctxt->spurs->flags1 & SF1_32_WORKLOADS)
@ -112,7 +112,7 @@ u32 cellSpursModulePollStatus(spu_thread& spu, u32* status)
// Exit current workload // Exit current workload
void cellSpursModuleExit(spu_thread& spu) void cellSpursModuleExit(spu_thread& spu)
{ {
auto ctxt = vm::_ptr<SpursKernelContext>(spu.offset + 0x100); auto ctxt = spu._ptr<SpursKernelContext>(0x100);
spu.pc = ctxt->exitToKernelAddr; spu.pc = ctxt->exitToKernelAddr;
// TODO: use g_escape for actual long jump // TODO: use g_escape for actual long jump
@ -246,7 +246,7 @@ s32 sys_spu_thread_switch_system_module(spu_thread& spu, u32 status)
// Select a workload to run // Select a workload to run
bool spursKernel1SelectWorkload(spu_thread& spu) bool spursKernel1SelectWorkload(spu_thread& spu)
{ {
auto ctxt = vm::_ptr<SpursKernelContext>(spu.offset + 0x100); const auto ctxt = spu._ptr<SpursKernelContext>(0x100);
// The first and only argument to this function is a boolean that is set to false if the function // The first and only argument to this function is a boolean that is set to false if the function
// is called by the SPURS kernel and set to true if called by cellSpursModulePollStatus. // is called by the SPURS kernel and set to true if called by cellSpursModulePollStatus.
@ -418,7 +418,7 @@ bool spursKernel1SelectWorkload(spu_thread& spu)
} }
} }
std::memcpy(vm::base(spu.offset + 0x100), spurs, 128); std::memcpy(ctxt, spurs, 128);
}//); }//);
u64 result = u64{wklSelectedId} << 32; u64 result = u64{wklSelectedId} << 32;
@ -430,7 +430,7 @@ bool spursKernel1SelectWorkload(spu_thread& spu)
// Select a workload to run // Select a workload to run
bool spursKernel2SelectWorkload(spu_thread& spu) bool spursKernel2SelectWorkload(spu_thread& spu)
{ {
auto ctxt = vm::_ptr<SpursKernelContext>(spu.offset + 0x100); const auto ctxt = spu._ptr<SpursKernelContext>(0x100);
// The first and only argument to this function is a boolean that is set to false if the function // The first and only argument to this function is a boolean that is set to false if the function
// is called by the SPURS kernel and set to true if called by cellSpursModulePollStatus. // is called by the SPURS kernel and set to true if called by cellSpursModulePollStatus.
@ -591,7 +591,7 @@ bool spursKernel2SelectWorkload(spu_thread& spu)
} }
} }
std::memcpy(vm::base(spu.offset + 0x100), spurs, 128); std::memcpy(ctxt, spurs, 128);
}//); }//);
u64 result = u64{wklSelectedId} << 32; u64 result = u64{wklSelectedId} << 32;
@ -603,7 +603,7 @@ bool spursKernel2SelectWorkload(spu_thread& spu)
// SPURS kernel dispatch workload // SPURS kernel dispatch workload
void spursKernelDispatchWorkload(spu_thread& spu, u64 widAndPollStatus) void spursKernelDispatchWorkload(spu_thread& spu, u64 widAndPollStatus)
{ {
auto ctxt = vm::_ptr<SpursKernelContext>(spu.offset + 0x100); const auto ctxt = spu._ptr<SpursKernelContext>(0x100);
auto isKernel2 = ctxt->spurs->flags1 & SF1_32_WORKLOADS ? true : false; auto isKernel2 = ctxt->spurs->flags1 & SF1_32_WORKLOADS ? true : false;
auto pollStatus = static_cast<u32>(widAndPollStatus); auto pollStatus = static_cast<u32>(widAndPollStatus);
@ -614,10 +614,10 @@ void spursKernelDispatchWorkload(spu_thread& spu, u64 widAndPollStatus)
wid < CELL_SPURS_MAX_WORKLOAD2 && isKernel2 ? &ctxt->spurs->wklInfo2[wid & 0xf] : wid < CELL_SPURS_MAX_WORKLOAD2 && isKernel2 ? &ctxt->spurs->wklInfo2[wid & 0xf] :
&ctxt->spurs->wklInfoSysSrv; &ctxt->spurs->wklInfoSysSrv;
std::memcpy(vm::base(spu.offset + 0x3FFE0), wklInfoOffset, 0x20); const auto wklInfo = spu._ptr<CellSpurs::WorkloadInfo>(0x3FFE0);
std::memcpy(wklInfo, wklInfoOffset, 0x20);
// Load the workload to LS // Load the workload to LS
auto wklInfo = vm::_ptr<CellSpurs::WorkloadInfo>(spu.offset + 0x3FFE0);
if (ctxt->wklCurrentAddr != wklInfo->addr) if (ctxt->wklCurrentAddr != wklInfo->addr)
{ {
switch (wklInfo->addr.addr()) switch (wklInfo->addr.addr())
@ -629,7 +629,7 @@ void spursKernelDispatchWorkload(spu_thread& spu, u64 widAndPollStatus)
//spu.RegisterHleFunction(0xA00, spursTasksetEntry); //spu.RegisterHleFunction(0xA00, spursTasksetEntry);
break; break;
default: default:
std::memcpy(vm::base(spu.offset + 0xA00), wklInfo->addr.get_ptr(), wklInfo->size); std::memcpy(spu._ptr<void>(0xA00), wklInfo->addr.get_ptr(), wklInfo->size);
break; break;
} }
@ -655,7 +655,7 @@ void spursKernelDispatchWorkload(spu_thread& spu, u64 widAndPollStatus)
// SPURS kernel workload exit // SPURS kernel workload exit
bool spursKernelWorkloadExit(spu_thread& spu) bool spursKernelWorkloadExit(spu_thread& spu)
{ {
auto ctxt = vm::_ptr<SpursKernelContext>(spu.offset + 0x100); const auto ctxt = spu._ptr<SpursKernelContext>(0x100);
auto isKernel2 = ctxt->spurs->flags1 & SF1_32_WORKLOADS ? true : false; auto isKernel2 = ctxt->spurs->flags1 & SF1_32_WORKLOADS ? true : false;
// Select next workload to run // Select next workload to run
@ -676,7 +676,7 @@ bool spursKernelWorkloadExit(spu_thread& spu)
// SPURS kernel entry point // SPURS kernel entry point
bool spursKernelEntry(spu_thread& spu) bool spursKernelEntry(spu_thread& spu)
{ {
auto ctxt = vm::_ptr<SpursKernelContext>(spu.offset + 0x100); const auto ctxt = spu._ptr<SpursKernelContext>(0x100);
memset(ctxt, 0, sizeof(SpursKernelContext)); memset(ctxt, 0, sizeof(SpursKernelContext));
// Save arguments // Save arguments
@ -726,7 +726,7 @@ bool spursKernelEntry(spu_thread& spu)
// Entry point of the system service // Entry point of the system service
bool spursSysServiceEntry(spu_thread& spu) bool spursSysServiceEntry(spu_thread& spu)
{ {
auto ctxt = vm::_ptr<SpursKernelContext>(spu.offset + spu.gpr[3]._u32[3]); const auto ctxt = spu._ptr<SpursKernelContext>(spu.gpr[3]._u32[3]);
auto arg = spu.gpr[4]._u64[1]; auto arg = spu.gpr[4]._u64[1];
auto pollStatus = spu.gpr[5]._u32[3]; auto pollStatus = spu.gpr[5]._u32[3];
@ -754,8 +754,8 @@ void spursSysServiceIdleHandler(spu_thread& spu, SpursKernelContext* ctxt)
while (true) while (true)
{ {
//vm::reservation_acquire(vm::base(spu.offset + 0x100), vm::cast(ctxt->spurs.addr(), HERE), 128); const auto spurs = spu._ptr<CellSpurs>(0x100);
auto spurs = vm::_ptr<CellSpurs>(spu.offset + 0x100); //vm::reservation_acquire(spurs, vm::cast(ctxt->spurs.addr(), HERE), 128);
// Find the number of SPUs that are idling in this SPURS instance // Find the number of SPUs that are idling in this SPURS instance
u32 nIdlingSpus = 0; u32 nIdlingSpus = 0;
@ -843,7 +843,7 @@ void spursSysServiceIdleHandler(spu_thread& spu, SpursKernelContext* ctxt)
continue; continue;
} }
//if (vm::reservation_update(vm::cast(ctxt->spurs.addr(), HERE), vm::base(spu.offset + 0x100), 128) && (shouldExit || foundReadyWorkload)) //if (vm::reservation_update(vm::cast(ctxt->spurs.addr(), HERE), spu._ptr<void>(0x100), 128) && (shouldExit || foundReadyWorkload))
{ {
break; break;
} }
@ -858,7 +858,7 @@ void spursSysServiceIdleHandler(spu_thread& spu, SpursKernelContext* ctxt)
// Main function for the system service // Main function for the system service
void spursSysServiceMain(spu_thread& spu, u32 pollStatus) void spursSysServiceMain(spu_thread& spu, u32 pollStatus)
{ {
auto ctxt = vm::_ptr<SpursKernelContext>(spu.offset + 0x100); const auto ctxt = spu._ptr<SpursKernelContext>(0x100);
if (!ctxt->spurs.aligned()) if (!ctxt->spurs.aligned())
{ {
@ -871,7 +871,7 @@ void spursSysServiceMain(spu_thread& spu, u32 pollStatus)
{ {
ctxt->sysSrvInitialised = 1; ctxt->sysSrvInitialised = 1;
//vm::reservation_acquire(vm::base(spu.offset + 0x100), vm::cast(ctxt->spurs.addr(), HERE), 128); //vm::reservation_acquire(ctxt, vm::cast(ctxt->spurs.addr(), HERE), 128);
//vm::reservation_op(ctxt->spurs.ptr(&CellSpurs::wklState1).addr(), 128, [&]() //vm::reservation_op(ctxt->spurs.ptr(&CellSpurs::wklState1).addr(), 128, [&]()
{ {
@ -886,7 +886,7 @@ void spursSysServiceMain(spu_thread& spu, u32 pollStatus)
spurs->sysSrvOnSpu |= 1 << ctxt->spuNum; spurs->sysSrvOnSpu |= 1 << ctxt->spuNum;
std::memcpy(vm::base(spu.offset + 0x2D80), spurs->wklState1, 128); std::memcpy(spu._ptr<void>(0x2D80), spurs->wklState1, 128);
}//); }//);
ctxt->traceBuffer = 0; ctxt->traceBuffer = 0;
@ -987,7 +987,7 @@ void spursSysServiceProcessRequests(spu_thread& spu, SpursKernelContext* ctxt)
updateTrace = true; updateTrace = true;
} }
std::memcpy(vm::base(spu.offset + 0x2D80), spurs->wklState1, 128); std::memcpy(spu._ptr<void>(0x2D80), spurs->wklState1, 128);
}//); }//);
// Process update workload message // Process update workload message
@ -1012,11 +1012,11 @@ void spursSysServiceProcessRequests(spu_thread& spu, SpursKernelContext* ctxt)
// Activate a workload // Activate a workload
void spursSysServiceActivateWorkload(spu_thread& spu, SpursKernelContext* ctxt) void spursSysServiceActivateWorkload(spu_thread& spu, SpursKernelContext* ctxt)
{ {
auto spurs = vm::_ptr<CellSpurs>(spu.offset + 0x100); const auto spurs = spu._ptr<CellSpurs>(0x100);
std::memcpy(vm::base(spu.offset + 0x30000), ctxt->spurs->wklInfo1, 0x200); std::memcpy(spu._ptr<void>(0x30000), ctxt->spurs->wklInfo1, 0x200);
if (spurs->flags1 & SF1_32_WORKLOADS) if (spurs->flags1 & SF1_32_WORKLOADS)
{ {
std::memcpy(vm::base(spu.offset + 0x30200), ctxt->spurs->wklInfo2, 0x200); std::memcpy(spu._ptr<void>(0x30200), ctxt->spurs->wklInfo2, 0x200);
} }
u32 wklShutdownBitSet = 0; u32 wklShutdownBitSet = 0;
@ -1024,7 +1024,7 @@ void spursSysServiceActivateWorkload(spu_thread& spu, SpursKernelContext* ctxt)
ctxt->wklRunnable2 = 0; ctxt->wklRunnable2 = 0;
for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++)
{ {
auto wklInfo1 = vm::_ptr<CellSpurs::WorkloadInfo>(spu.offset + 0x30000); const auto wklInfo1 = spu._ptr<CellSpurs::WorkloadInfo>(0x30000);
// Copy the priority of the workload for this SPU and its unique id to the LS // Copy the priority of the workload for this SPU and its unique id to the LS
ctxt->priority[i] = wklInfo1[i].priority[ctxt->spuNum] == 0 ? 0 : 0x10 - wklInfo1[i].priority[ctxt->spuNum]; ctxt->priority[i] = wklInfo1[i].priority[ctxt->spuNum] == 0 ? 0 : 0x10 - wklInfo1[i].priority[ctxt->spuNum];
@ -1032,7 +1032,7 @@ void spursSysServiceActivateWorkload(spu_thread& spu, SpursKernelContext* ctxt)
if (spurs->flags1 & SF1_32_WORKLOADS) if (spurs->flags1 & SF1_32_WORKLOADS)
{ {
auto wklInfo2 = vm::_ptr<CellSpurs::WorkloadInfo>(spu.offset + 0x30200); const auto wklInfo2 = spu._ptr<CellSpurs::WorkloadInfo>(0x30200);
// Copy the priority of the workload for this SPU to the LS // Copy the priority of the workload for this SPU to the LS
if (wklInfo2[i].priority[ctxt->spuNum]) if (wklInfo2[i].priority[ctxt->spuNum])
@ -1098,7 +1098,7 @@ void spursSysServiceActivateWorkload(spu_thread& spu, SpursKernelContext* ctxt)
} }
} }
std::memcpy(vm::base(spu.offset + 0x2D80), spurs->wklState1, 128); std::memcpy(spu._ptr<void>(0x2D80), spurs->wklState1, 128);
}//); }//);
if (wklShutdownBitSet) if (wklShutdownBitSet)
@ -1141,7 +1141,7 @@ void spursSysServiceUpdateShutdownCompletionEvents(spu_thread& spu, SpursKernelC
} }
} }
std::memcpy(vm::base(spu.offset + 0x2D80), spurs->wklState1, 128); std::memcpy(spu._ptr<void>(0x2D80), spurs->wklState1, 128);
}//); }//);
if (wklNotifyBitSet) if (wklNotifyBitSet)
@ -1189,14 +1189,14 @@ void spursSysServiceTraceUpdate(spu_thread& spu, SpursKernelContext* ctxt, u32 a
notify = true; notify = true;
} }
std::memcpy(vm::base(spu.offset + 0x2D80), spurs->wklState1, 128); std::memcpy(spu._ptr<void>(0x2D80), spurs->wklState1, 128);
}//); }//);
// Get trace parameters from CellSpurs and store them in the LS // Get trace parameters from CellSpurs and store them in the LS
if (((sysSrvMsgUpdateTrace & (1 << ctxt->spuNum)) != 0) || (arg3 != 0)) if (((sysSrvMsgUpdateTrace & (1 << ctxt->spuNum)) != 0) || (arg3 != 0))
{ {
//vm::reservation_acquire(vm::base(spu.offset + 0x80), ctxt->spurs.ptr(&CellSpurs::traceBuffer).addr(), 128); //vm::reservation_acquire(spu._ptr<void>(0x80), ctxt->spurs.ptr(&CellSpurs::traceBuffer).addr(), 128);
auto spurs = vm::_ptr<CellSpurs>(spu.offset + 0x80 - offset32(&CellSpurs::traceBuffer)); auto spurs = spu._ptr<CellSpurs>(0x80 - offset32(&CellSpurs::traceBuffer));
if (ctxt->traceMsgCount != 0xffu || spurs->traceBuffer.addr() == 0u) if (ctxt->traceMsgCount != 0xffu || spurs->traceBuffer.addr() == 0u)
{ {
@ -1204,8 +1204,8 @@ void spursSysServiceTraceUpdate(spu_thread& spu, SpursKernelContext* ctxt, u32 a
} }
else else
{ {
std::memcpy(vm::base(spu.offset + 0x2C00), vm::base(vm::cast(spurs->traceBuffer.addr(), HERE) & -0x4), 0x80); const auto traceBuffer = spu._ptr<CellSpursTraceInfo>(0x2C00);
auto traceBuffer = vm::_ptr<CellSpursTraceInfo>(spu.offset + 0x2C00); std::memcpy(traceBuffer, vm::base(vm::cast(spurs->traceBuffer.addr(), HERE) & -0x4), 0x80);
ctxt->traceMsgCount = traceBuffer->count[ctxt->spuNum]; ctxt->traceMsgCount = traceBuffer->count[ctxt->spuNum];
} }
@ -1219,7 +1219,7 @@ void spursSysServiceTraceUpdate(spu_thread& spu, SpursKernelContext* ctxt, u32 a
if (notify) if (notify)
{ {
auto spurs = vm::_ptr<CellSpurs>(spu.offset + 0x2D80 - offset32(&CellSpurs::wklState1)); auto spurs = spu._ptr<CellSpurs>(0x2D80 - offset32(&CellSpurs::wklState1));
sys_spu_thread_send_event(spu, spurs->spuPort, 2, 0); sys_spu_thread_send_event(spu, spurs->spuPort, 2, 0);
} }
} }
@ -1244,7 +1244,7 @@ void spursSysServiceCleanupAfterSystemWorkload(spu_thread& spu, SpursKernelConte
wklId = spurs->sysSrvPreemptWklId[ctxt->spuNum]; wklId = spurs->sysSrvPreemptWklId[ctxt->spuNum];
spurs->sysSrvPreemptWklId[ctxt->spuNum] = 0xFF; spurs->sysSrvPreemptWklId[ctxt->spuNum] = 0xFF;
std::memcpy(vm::base(spu.offset + 0x2D80), spurs->wklState1, 128); std::memcpy(spu._ptr<void>(0x2D80), spurs->wklState1, 128);
}//); }//);
if (do_return) return; if (do_return) return;
@ -1266,7 +1266,7 @@ void spursSysServiceCleanupAfterSystemWorkload(spu_thread& spu, SpursKernelConte
spurs->wklIdleSpuCountOrReadyCount2[wklId & 0x0F].raw() -= 1; spurs->wklIdleSpuCountOrReadyCount2[wklId & 0x0F].raw() -= 1;
} }
std::memcpy(vm::base(spu.offset + 0x100), spurs, 128); std::memcpy(spu._ptr<void>(0x100), spurs, 128);
}//); }//);
// Set the current workload id to the id of the pre-empted workload since cellSpursModulePutTrace // Set the current workload id to the id of the pre-empted workload since cellSpursModulePutTrace
@ -1302,8 +1302,8 @@ enum SpursTasksetRequest
// Taskset PM entry point // Taskset PM entry point
bool spursTasksetEntry(spu_thread& spu) bool spursTasksetEntry(spu_thread& spu)
{ {
auto ctxt = vm::_ptr<SpursTasksetContext>(spu.offset + 0x2700); auto ctxt = spu._ptr<SpursTasksetContext>(0x2700);
auto kernelCtxt = vm::_ptr<SpursKernelContext>(spu.offset + spu.gpr[3]._u32[3]); auto kernelCtxt = spu._ptr<SpursKernelContext>(spu.gpr[3]._u32[3]);
auto arg = spu.gpr[4]._u64[1]; auto arg = spu.gpr[4]._u64[1];
auto pollStatus = spu.gpr[5]._u32[3]; auto pollStatus = spu.gpr[5]._u32[3];
@ -1337,7 +1337,7 @@ bool spursTasksetEntry(spu_thread& spu)
// Entry point into the Taskset PM for task syscalls // Entry point into the Taskset PM for task syscalls
bool spursTasksetSyscallEntry(spu_thread& spu) bool spursTasksetSyscallEntry(spu_thread& spu)
{ {
auto ctxt = vm::_ptr<SpursTasksetContext>(spu.offset + 0x2700); auto ctxt = spu._ptr<SpursTasksetContext>(0x2700);
{ {
// Save task context // Save task context
@ -1364,7 +1364,7 @@ bool spursTasksetSyscallEntry(spu_thread& spu)
// Resume a task // Resume a task
void spursTasksetResumeTask(spu_thread& spu) void spursTasksetResumeTask(spu_thread& spu)
{ {
auto ctxt = vm::_ptr<SpursTasksetContext>(spu.offset + 0x2700); auto ctxt = spu._ptr<SpursTasksetContext>(0x2700);
// Restore task context // Restore task context
spu.gpr[0] = ctxt->savedContextLr; spu.gpr[0] = ctxt->savedContextLr;
@ -1380,8 +1380,8 @@ void spursTasksetResumeTask(spu_thread& spu)
// Start a task // Start a task
void spursTasksetStartTask(spu_thread& spu, CellSpursTaskArgument& taskArgs) void spursTasksetStartTask(spu_thread& spu, CellSpursTaskArgument& taskArgs)
{ {
auto ctxt = vm::_ptr<SpursTasksetContext>(spu.offset + 0x2700); auto ctxt = spu._ptr<SpursTasksetContext>(0x2700);
auto taskset = vm::_ptr<CellSpursTaskset>(spu.offset + 0x2700); auto taskset = spu._ptr<CellSpursTaskset>(0x2700);
spu.gpr[2].clear(); spu.gpr[2].clear();
spu.gpr[3] = v128::from64r(taskArgs._u64[0], taskArgs._u64[1]); spu.gpr[3] = v128::from64r(taskArgs._u64[0], taskArgs._u64[1]);
@ -1398,8 +1398,8 @@ void spursTasksetStartTask(spu_thread& spu, CellSpursTaskArgument& taskArgs)
// Process a request and update the state of the taskset // Process a request and update the state of the taskset
s32 spursTasksetProcessRequest(spu_thread& spu, s32 request, u32* taskId, u32* isWaiting) s32 spursTasksetProcessRequest(spu_thread& spu, s32 request, u32* taskId, u32* isWaiting)
{ {
auto kernelCtxt = vm::_ptr<SpursKernelContext>(spu.offset + 0x100); auto kernelCtxt = spu._ptr<SpursKernelContext>(0x100);
auto ctxt = vm::_ptr<SpursTasksetContext>(spu.offset + 0x2700); auto ctxt = spu._ptr<SpursTasksetContext>(0x2700);
s32 rc = CELL_OK; s32 rc = CELL_OK;
s32 numNewlyReadyTasks; s32 numNewlyReadyTasks;
@ -1561,7 +1561,7 @@ s32 spursTasksetProcessRequest(spu_thread& spu, s32 request, u32* taskId, u32* i
taskset->signalled = signalled; taskset->signalled = signalled;
taskset->ready = ready; taskset->ready = ready;
std::memcpy(vm::base(spu.offset + 0x2700), taskset, 128); std::memcpy(spu._ptr<void>(0x2700), taskset, 128);
}//); }//);
// Increment the ready count of the workload by the number of tasks that have become ready // Increment the ready count of the workload by the number of tasks that have become ready
@ -1582,7 +1582,7 @@ s32 spursTasksetProcessRequest(spu_thread& spu, s32 request, u32* taskId, u32* i
spurs->wklIdleSpuCountOrReadyCount2[kernelCtxt->wklCurrentId & 0x0F] = readyCount; spurs->wklIdleSpuCountOrReadyCount2[kernelCtxt->wklCurrentId & 0x0F] = readyCount;
} }
std::memcpy(vm::base(spu.offset + 0x100), spurs, 128); std::memcpy(spu._ptr<void>(0x100), spurs, 128);
}//); }//);
return rc; return rc;
@ -1614,7 +1614,7 @@ bool spursTasksetPollStatus(spu_thread& spu)
// Exit the Taskset PM // Exit the Taskset PM
void spursTasksetExit(spu_thread& spu) void spursTasksetExit(spu_thread& spu)
{ {
auto ctxt = vm::_ptr<SpursTasksetContext>(spu.offset + 0x2700); auto ctxt = spu._ptr<SpursTasksetContext>(0x2700);
// Trace - STOP // Trace - STOP
CellSpursTracePacket pkt{}; CellSpursTracePacket pkt{};
@ -1635,9 +1635,9 @@ void spursTasksetExit(spu_thread& spu)
// Invoked when a task exits // Invoked when a task exits
void spursTasksetOnTaskExit(spu_thread& spu, u64 addr, u32 taskId, s32 exitCode, u64 args) void spursTasksetOnTaskExit(spu_thread& spu, u64 addr, u32 taskId, s32 exitCode, u64 args)
{ {
auto ctxt = vm::_ptr<SpursTasksetContext>(spu.offset + 0x2700); auto ctxt = spu._ptr<SpursTasksetContext>(0x2700);
std::memcpy(vm::base(spu.offset + 0x10000), vm::base(addr & -0x80), (addr & 0x7F) << 11); std::memcpy(spu._ptr<void>(0x10000), vm::base(addr & -0x80), (addr & 0x7F) << 11);
spu.gpr[3]._u64[1] = ctxt->taskset.addr(); spu.gpr[3]._u64[1] = ctxt->taskset.addr();
spu.gpr[4]._u32[3] = taskId; spu.gpr[4]._u32[3] = taskId;
@ -1649,8 +1649,8 @@ void spursTasksetOnTaskExit(spu_thread& spu, u64 addr, u32 taskId, s32 exitCode,
// Save the context of a task // Save the context of a task
s32 spursTasketSaveTaskContext(spu_thread& spu) s32 spursTasketSaveTaskContext(spu_thread& spu)
{ {
auto ctxt = vm::_ptr<SpursTasksetContext>(spu.offset + 0x2700); auto ctxt = spu._ptr<SpursTasksetContext>(0x2700);
auto taskInfo = vm::_ptr<CellSpursTaskset::TaskInfo>(spu.offset + 0x2780); auto taskInfo = spu._ptr<CellSpursTaskset::TaskInfo>(0x2780);
//spursDmaWaitForCompletion(spu, 0xFFFFFFFF); //spursDmaWaitForCompletion(spu, 0xFFFFFFFF);
@ -1693,7 +1693,7 @@ s32 spursTasketSaveTaskContext(spu_thread& spu)
// Store the processor context // Store the processor context
const u32 contextSaveStorage = vm::cast(taskInfo->context_save_storage_and_alloc_ls_blocks & -0x80, HERE); const u32 contextSaveStorage = vm::cast(taskInfo->context_save_storage_and_alloc_ls_blocks & -0x80, HERE);
std::memcpy(vm::base(contextSaveStorage), vm::base(spu.offset + 0x2C80), 0x380); std::memcpy(vm::base(contextSaveStorage), spu._ptr<void>(0x2C80), 0x380);
// Save LS context // Save LS context
for (auto i = 6; i < 128; i++) for (auto i = 6; i < 128; i++)
@ -1701,7 +1701,7 @@ s32 spursTasketSaveTaskContext(spu_thread& spu)
if (ls_pattern._bit[i]) if (ls_pattern._bit[i])
{ {
// TODO: Combine DMA requests for consecutive blocks into a single request // TODO: Combine DMA requests for consecutive blocks into a single request
std::memcpy(vm::base(contextSaveStorage + 0x400 + ((i - 6) << 11)), vm::base(spu.offset + CELL_SPURS_TASK_TOP + ((i - 6) << 11)), 0x800); std::memcpy(vm::base(contextSaveStorage + 0x400 + ((i - 6) << 11)), spu._ptr<void>(CELL_SPURS_TASK_TOP + ((i - 6) << 11)), 0x800);
} }
} }
@ -1712,8 +1712,8 @@ s32 spursTasketSaveTaskContext(spu_thread& spu)
// Taskset dispatcher // Taskset dispatcher
void spursTasksetDispatch(spu_thread& spu) void spursTasksetDispatch(spu_thread& spu)
{ {
auto ctxt = vm::_ptr<SpursTasksetContext>(spu.offset + 0x2700); const auto ctxt = spu._ptr<SpursTasksetContext>(0x2700);
auto taskset = vm::_ptr<CellSpursTaskset>(spu.offset + 0x2700); const auto taskset = spu._ptr<CellSpursTaskset>(0x2700);
u32 taskId; u32 taskId;
u32 isWaiting; u32 isWaiting;
@ -1727,8 +1727,8 @@ void spursTasksetDispatch(spu_thread& spu)
ctxt->taskId = taskId; ctxt->taskId = taskId;
// DMA in the task info for the selected task // DMA in the task info for the selected task
std::memcpy(vm::base(spu.offset + 0x2780), &ctxt->taskset->task_info[taskId], sizeof(CellSpursTaskset::TaskInfo)); const auto taskInfo = spu._ptr<CellSpursTaskset::TaskInfo>(0x2780);
auto taskInfo = vm::_ptr<CellSpursTaskset::TaskInfo>(spu.offset + 0x2780); std::memcpy(taskInfo, &ctxt->taskset->task_info[taskId], sizeof(CellSpursTaskset::TaskInfo));
auto elfAddr = taskInfo->elf.addr().value(); auto elfAddr = taskInfo->elf.addr().value();
taskInfo->elf.set(taskInfo->elf.addr() & 0xFFFFFFFFFFFFFFF8); taskInfo->elf.set(taskInfo->elf.addr() & 0xFFFFFFFFFFFFFFF8);
@ -1742,7 +1742,7 @@ void spursTasksetDispatch(spu_thread& spu)
if (isWaiting == 0) if (isWaiting == 0)
{ {
// If we reach here it means that the task is being started and not being resumed // If we reach here it means that the task is being started and not being resumed
std::memset(vm::base(spu.offset + CELL_SPURS_TASK_TOP), 0, CELL_SPURS_TASK_BOTTOM - CELL_SPURS_TASK_TOP); std::memset(spu._ptr<void>(CELL_SPURS_TASK_TOP), 0, CELL_SPURS_TASK_BOTTOM - CELL_SPURS_TASK_TOP);
ctxt->guidAddr = CELL_SPURS_TASK_TOP; ctxt->guidAddr = CELL_SPURS_TASK_TOP;
u32 entryPoint; u32 entryPoint;
@ -1764,7 +1764,7 @@ void spursTasksetDispatch(spu_thread& spu)
if ((elfAddr & 5) == 1) if ((elfAddr & 5) == 1)
{ {
std::memcpy(vm::base(spu.offset + 0x2FC0), &vm::_ptr<CellSpursTaskset2>(vm::cast(ctxt->taskset.addr()))->task_exit_code[taskId], 0x10); std::memcpy(spu._ptr<void>(0x2FC0), &vm::_ptr<CellSpursTaskset2>(vm::cast(ctxt->taskset.addr()))->task_exit_code[taskId], 0x10);
} }
// Trace - GUID // Trace - GUID
@ -1785,7 +1785,7 @@ void spursTasksetDispatch(spu_thread& spu)
{ {
if (taskset->enable_clear_ls) if (taskset->enable_clear_ls)
{ {
std::memset(vm::base(spu.offset + CELL_SPURS_TASK_TOP), 0, CELL_SPURS_TASK_BOTTOM - CELL_SPURS_TASK_TOP); std::memset(spu._ptr<void>(CELL_SPURS_TASK_TOP), 0, CELL_SPURS_TASK_BOTTOM - CELL_SPURS_TASK_TOP);
} }
// If the entire LS is saved then there is no need to load the ELF as it will be be saved in the context save area as well // If the entire LS is saved then there is no need to load the ELF as it will be be saved in the context save area as well
@ -1803,13 +1803,13 @@ void spursTasksetDispatch(spu_thread& spu)
// Load saved context from main memory to LS // Load saved context from main memory to LS
const u32 contextSaveStorage = vm::cast(taskInfo->context_save_storage_and_alloc_ls_blocks & -0x80, HERE); const u32 contextSaveStorage = vm::cast(taskInfo->context_save_storage_and_alloc_ls_blocks & -0x80, HERE);
std::memcpy(vm::base(spu.offset + 0x2C80), vm::base(contextSaveStorage), 0x380); std::memcpy(spu._ptr<void>(0x2C80), vm::base(contextSaveStorage), 0x380);
for (auto i = 6; i < 128; i++) for (auto i = 6; i < 128; i++)
{ {
if (ls_pattern._bit[i]) if (ls_pattern._bit[i])
{ {
// TODO: Combine DMA requests for consecutive blocks into a single request // TODO: Combine DMA requests for consecutive blocks into a single request
std::memcpy(vm::base(spu.offset + CELL_SPURS_TASK_TOP + ((i - 6) << 11)), vm::base(contextSaveStorage + 0x400 + ((i - 6) << 11)), 0x800); std::memcpy(spu._ptr<void>(CELL_SPURS_TASK_TOP + ((i - 6) << 11)), vm::base(contextSaveStorage + 0x400 + ((i - 6) << 11)), 0x800);
} }
} }
@ -1840,8 +1840,8 @@ void spursTasksetDispatch(spu_thread& spu)
// Process a syscall request // Process a syscall request
s32 spursTasksetProcessSyscall(spu_thread& spu, u32 syscallNum, u32 args) s32 spursTasksetProcessSyscall(spu_thread& spu, u32 syscallNum, u32 args)
{ {
auto ctxt = vm::_ptr<SpursTasksetContext>(spu.offset + 0x2700); auto ctxt = spu._ptr<SpursTasksetContext>(0x2700);
auto taskset = vm::_ptr<CellSpursTaskset>(spu.offset + 0x2700); auto taskset = spu._ptr<CellSpursTaskset>(0x2700);
// If the 0x10 bit is set in syscallNum then its the 2nd version of the // If the 0x10 bit is set in syscallNum then its the 2nd version of the
// syscall (e.g. cellSpursYield2 instead of cellSpursYield) and so don't wait // syscall (e.g. cellSpursYield2 instead of cellSpursYield) and so don't wait
@ -1931,7 +1931,7 @@ s32 spursTasksetProcessSyscall(spu_thread& spu, u32 syscallNum, u32 args)
cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); cellSpursModulePutTrace(&pkt, ctxt->dmaTagId);
// Clear the GUID of the task // Clear the GUID of the task
std::memset(vm::base(spu.offset + ctxt->guidAddr), 0, 0x10); std::memset(spu._ptr<void>(ctxt->guidAddr), 0, 0x10);
if (spursTasksetPollStatus(spu)) if (spursTasksetPollStatus(spu))
{ {
@ -1949,8 +1949,8 @@ s32 spursTasksetProcessSyscall(spu_thread& spu, u32 syscallNum, u32 args)
// Initialise the Taskset PM // Initialise the Taskset PM
void spursTasksetInit(spu_thread& spu, u32 pollStatus) void spursTasksetInit(spu_thread& spu, u32 pollStatus)
{ {
auto ctxt = vm::_ptr<SpursTasksetContext>(spu.offset + 0x2700); auto ctxt = spu._ptr<SpursTasksetContext>(0x2700);
auto kernelCtxt = vm::_ptr<SpursKernelContext>(spu.offset + 0x100); auto kernelCtxt = spu._ptr<SpursKernelContext>(0x100);
kernelCtxt->moduleId[0] = 'T'; kernelCtxt->moduleId[0] = 'T';
kernelCtxt->moduleId[1] = 'K'; kernelCtxt->moduleId[1] = 'K';
@ -2014,7 +2014,7 @@ s32 spursTasksetLoadElf(spu_thread& spu, u32* entryPoint, u32* lowestLoadAddr, u
{ {
if (skipWriteableSegments == false || (prog.p_flags & 2u) == 0u) if (skipWriteableSegments == false || (prog.p_flags & 2u) == 0u)
{ {
std::memcpy(vm::base(spu.offset + prog.p_vaddr), prog.bin.data(), prog.p_filesz); std::memcpy(spu._ptr<void>(prog.p_vaddr), prog.bin.data(), prog.p_filesz);
} }
} }
} }

View File

@ -391,7 +391,7 @@ s32 sys_raw_spu_load(s32 id, vm::cptr<char> path, vm::ptr<u32> entry)
sys_spu_image img; sys_spu_image img;
img.load(elf_file); img.load(elf_file);
img.deploy(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id, img.segs.get_ptr(), img.nsegs); img.deploy(vm::_ptr<u8>(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id), img.segs.get_ptr(), img.nsegs);
img.free(); img.free();
*entry = img.entry_point; *entry = img.entry_point;
@ -404,7 +404,7 @@ s32 sys_raw_spu_image_load(ppu_thread& ppu, s32 id, vm::ptr<sys_spu_image> img)
sysPrxForUser.warning("sys_raw_spu_image_load(id=%d, img=*0x%x)", id, img); sysPrxForUser.warning("sys_raw_spu_image_load(id=%d, img=*0x%x)", id, img);
// Load SPU segments // Load SPU segments
img->deploy(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id, img->segs.get_ptr(), img->nsegs); img->deploy(vm::_ptr<u8>(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id), img->segs.get_ptr(), img->nsegs);
// Use MMIO // Use MMIO
vm::write32(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id + RAW_SPU_PROB_OFFSET + SPU_NPC_offs, img->entry_point); vm::write32(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id + RAW_SPU_PROB_OFFSET + SPU_NPC_offs, img->entry_point);

View File

@ -1659,8 +1659,8 @@ void spu_recompiler::RDCH(spu_opcode_t op)
{ {
const XmmLink& vr = XmmAlloc(); const XmmLink& vr = XmmAlloc();
c->movzx(*addr, SPU_OFF_8(interrupts_enabled)); c->movzx(*addr, SPU_OFF_8(interrupts_enabled));
c->movzx(arg1->r32(), SPU_OFF_8(is_isolated)); c->mov(arg1->r32(), SPU_OFF_32(thread_type));
c->shl(arg1->r32(), 1); c->and_(arg1->r32(), 2);
c->or_(addr->r32(), arg1->r32()); c->or_(addr->r32(), arg1->r32());
c->movd(vr, *addr); c->movd(vr, *addr);
c->pslldq(vr, 12); c->pslldq(vr, 12);

View File

@ -5502,7 +5502,7 @@ public:
case SPU_RdMachStat: case SPU_RdMachStat:
{ {
res.value = m_ir->CreateZExt(m_ir->CreateLoad(spu_ptr<u8>(&spu_thread::interrupts_enabled)), get_type<u32>()); res.value = m_ir->CreateZExt(m_ir->CreateLoad(spu_ptr<u8>(&spu_thread::interrupts_enabled)), get_type<u32>());
res.value = m_ir->CreateOr(res.value, m_ir->CreateShl(m_ir->CreateZExt(m_ir->CreateLoad(spu_ptr<u8>(&spu_thread::is_isolated)), get_type<u32>()), m_ir->getInt32(1))); res.value = m_ir->CreateOr(res.value, m_ir->CreateAnd(m_ir->CreateLoad(spu_ptr<u32>(&spu_thread::thread_type)), m_ir->getInt32(2)));
break; break;
} }

View File

@ -59,6 +59,22 @@ void fmt_class_string<mfc_tag_update>::format(std::string& out, u64 arg)
}); });
} }
template <>
void fmt_class_string<spu_type>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](spu_type arg)
{
switch (arg)
{
case spu_type::threaded: return "Threaded";
case spu_type::raw: return "Raw";
case spu_type::isolated: return "Isolated";
}
return unknown;
});
}
// Verify AVX availability for TSX transactions // Verify AVX availability for TSX transactions
static const bool s_tsx_avx = utils::has_avx(); static const bool s_tsx_avx = utils::has_avx();
@ -968,7 +984,7 @@ void spu_thread::cpu_init()
ch_dec_start_timestamp = get_timebased_time(); // ??? ch_dec_start_timestamp = get_timebased_time(); // ???
ch_dec_value = 0; ch_dec_value = 0;
if (offset >= RAW_SPU_BASE_ADDR) if (get_type() >= spu_type::raw)
{ {
ch_in_mbox.clear(); ch_in_mbox.clear();
ch_snr1.data.raw() = {}; ch_snr1.data.raw() = {};
@ -980,7 +996,7 @@ void spu_thread::cpu_init()
mfc_prxy_write_state = {}; mfc_prxy_write_state = {};
} }
status_npc.raw() = {is_isolated ? SPU_STATUS_IS_ISOLATED : 0, 0}; status_npc.raw() = {get_type() == spu_type::isolated ? SPU_STATUS_IS_ISOLATED : 0, 0};
run_ctrl.raw() = 0; run_ctrl.raw() = 0;
int_ctrl[0].clear(); int_ctrl[0].clear();
@ -992,7 +1008,7 @@ void spu_thread::cpu_init()
void spu_thread::cpu_stop() void spu_thread::cpu_stop()
{ {
if (!group && offset >= RAW_SPU_BASE_ADDR) if (get_type() >= spu_type::raw)
{ {
if (status_npc.fetch_op([this](status_npc_sync_var& state) if (status_npc.fetch_op([this](status_npc_sync_var& state)
{ {
@ -1011,7 +1027,7 @@ void spu_thread::cpu_stop()
status_npc.notify_one(); status_npc.notify_one();
} }
} }
else if (group && is_stopped()) else if (is_stopped())
{ {
ch_in_mbox.clear(); ch_in_mbox.clear();
@ -1092,7 +1108,8 @@ void spu_thread::cpu_task()
name_cache = cpu->spu_tname.load(); name_cache = cpu->spu_tname.load();
} }
return fmt::format("%sSPU[0x%07x] Thread (%s) [0x%05x]", cpu->offset >= RAW_SPU_BASE_ADDR ? cpu->is_isolated ? "Iso" : "Raw" : "", cpu->lv2_id, *name_cache.get(), cpu->pc); const auto type = cpu->get_type();
return fmt::format("%sSPU[0x%07x] Thread (%s) [0x%05x]", type >= spu_type::raw ? type == spu_type::isolated ? "Iso" : "Raw" : "", cpu->lv2_id, *name_cache.get(), cpu->pc);
}; };
if (jit) if (jit)
@ -1166,7 +1183,7 @@ spu_thread::~spu_thread()
utils::memory_release(ls - SPU_LS_SIZE, SPU_LS_SIZE * 3); utils::memory_release(ls - SPU_LS_SIZE, SPU_LS_SIZE * 3);
// Deallocate RawSPU ID // Deallocate RawSPU ID
if (!group && offset >= RAW_SPU_BASE_ADDR) if (get_type() >= spu_type::raw)
{ {
g_raw_spu_id[index] = 0; g_raw_spu_id[index] = 0;
g_raw_spu_ctr--; g_raw_spu_ctr--;
@ -1175,9 +1192,7 @@ spu_thread::~spu_thread()
spu_thread::spu_thread(vm::addr_t _ls, lv2_spu_group* group, u32 index, std::string_view name, u32 lv2_id, bool is_isolated) spu_thread::spu_thread(vm::addr_t _ls, lv2_spu_group* group, u32 index, std::string_view name, u32 lv2_id, bool is_isolated)
: cpu_thread(idm::last_id()) : cpu_thread(idm::last_id())
, is_isolated(is_isolated)
, index(index) , index(index)
, offset(_ls)
, ls([&]() , ls([&]()
{ {
const auto [_, shm] = vm::get(vm::any, _ls)->get(_ls); const auto [_, shm] = vm::get(vm::any, _ls)->get(_ls);
@ -1193,6 +1208,8 @@ spu_thread::spu_thread(vm::addr_t _ls, lv2_spu_group* group, u32 index, std::str
// Use the middle mirror // Use the middle mirror
return addr + SPU_LS_SIZE; return addr + SPU_LS_SIZE;
}()) }())
, thread_type(group ? spu_type::threaded : is_isolated ? spu_type::isolated : spu_type::raw)
, offset(_ls)
, group(group) , group(group)
, lv2_id(lv2_id) , lv2_id(lv2_id)
, spu_tname(stx::shared_cptr<std::string>::make(name)) , spu_tname(stx::shared_cptr<std::string>::make(name))
@ -1216,7 +1233,7 @@ spu_thread::spu_thread(vm::addr_t _ls, lv2_spu_group* group, u32 index, std::str
} }
} }
if (!group && offset >= RAW_SPU_BASE_ADDR) if (get_type() >= spu_type::raw)
{ {
cpu_init(); cpu_init();
} }
@ -1279,7 +1296,7 @@ void spu_thread::do_dma_transfer(const spu_mfc_cmd& args)
fmt::throw_exception("Invalid RawSPU MMIO offset (cmd=0x%x, lsa=0x%x, ea=0x%llx, tag=0x%x, size=0x%x)" HERE, args.cmd, args.lsa, args.eal, args.tag, args.size); fmt::throw_exception("Invalid RawSPU MMIO offset (cmd=0x%x, lsa=0x%x, ea=0x%llx, tag=0x%x, size=0x%x)" HERE, args.cmd, args.lsa, args.eal, args.tag, args.size);
} }
} }
else if (this->offset >= RAW_SPU_BASE_ADDR) else if (get_type() >= spu_type::raw)
{ {
fmt::throw_exception("SPU MMIO used for RawSPU (cmd=0x%x, lsa=0x%x, ea=0x%llx, tag=0x%x, size=0x%x)" HERE, args.cmd, args.lsa, args.eal, args.tag, args.size); fmt::throw_exception("SPU MMIO used for RawSPU (cmd=0x%x, lsa=0x%x, ea=0x%llx, tag=0x%x, size=0x%x)" HERE, args.cmd, args.lsa, args.eal, args.tag, args.size);
} }
@ -2618,7 +2635,7 @@ s64 spu_thread::get_ch_value(u32 ch)
case SPU_RdMachStat: case SPU_RdMachStat:
{ {
// Return SPU Interrupt status in LSB // Return SPU Interrupt status in LSB
return u32{interrupts_enabled} | (u32{is_isolated} << 1); return u32{interrupts_enabled} | (u32{get_type() == spu_type::isolated} << 1);
} }
} }
@ -2639,7 +2656,7 @@ bool spu_thread::set_ch_value(u32 ch, u32 value)
case SPU_WrOutIntrMbox: case SPU_WrOutIntrMbox:
{ {
if (offset >= RAW_SPU_BASE_ADDR) if (get_type() >= spu_type::raw)
{ {
while (!ch_out_intr_mbox.try_push(value)) while (!ch_out_intr_mbox.try_push(value))
{ {
@ -2957,7 +2974,7 @@ bool spu_thread::stop_and_signal(u32 code)
}); });
}; };
if (offset >= RAW_SPU_BASE_ADDR) if (get_type() >= spu_type::raw)
{ {
// Save next PC and current SPU Interrupt Status // Save next PC and current SPU Interrupt Status
state += cpu_flag::stop + cpu_flag::wait; state += cpu_flag::stop + cpu_flag::wait;
@ -3351,7 +3368,7 @@ void spu_thread::halt()
{ {
spu_log.trace("halt()"); spu_log.trace("halt()");
if (offset >= RAW_SPU_BASE_ADDR) if (get_type() >= spu_type::raw)
{ {
state += cpu_flag::stop + cpu_flag::wait; state += cpu_flag::stop + cpu_flag::wait;

View File

@ -533,6 +533,13 @@ public:
} }
}; };
enum class spu_type : u32
{
threaded,
raw,
isolated,
};
class spu_thread : public cpu_thread class spu_thread : public cpu_thread
{ {
public: public:
@ -630,7 +637,6 @@ public:
u32 npc; // SPU Next Program Counter register u32 npc; // SPU Next Program Counter register
}; };
const bool is_isolated;
atomic_t<status_npc_sync_var> status_npc; atomic_t<status_npc_sync_var> status_npc;
std::array<spu_int_ctrl_t, 3> int_ctrl; // SPU Class 0, 1, 2 Interrupt Management std::array<spu_int_ctrl_t, 3> int_ctrl; // SPU Class 0, 1, 2 Interrupt Management
@ -640,9 +646,10 @@ public:
atomic_t<u32> last_exit_status; // Value to be written in exit_status after checking group termination atomic_t<u32> last_exit_status; // Value to be written in exit_status after checking group termination
const u32 index; // SPU index const u32 index; // SPU index
const u32 offset; // SPU LS offset
const std::add_pointer_t<u8> ls; // SPU LS pointer const std::add_pointer_t<u8> ls; // SPU LS pointer
const spu_type thread_type;
private: private:
const u32 offset; // SPU LS offset
lv2_spu_group* const group; // SPU Thread Group (only safe to access in the spu thread itself) lv2_spu_group* const group; // SPU Thread Group (only safe to access in the spu thread itself)
public: public:
const u32 lv2_id; // The actual id that is used by syscalls const u32 lv2_id; // The actual id that is used by syscalls
@ -686,18 +693,23 @@ public:
// Convert specified SPU LS address to a pointer of specified (possibly converted to BE) type // Convert specified SPU LS address to a pointer of specified (possibly converted to BE) type
template<typename T> template<typename T>
inline to_be_t<T>* _ptr(u32 lsa) to_be_t<T>* _ptr(u32 lsa) const
{ {
return reinterpret_cast<to_be_t<T>*>(ls + lsa); return reinterpret_cast<to_be_t<T>*>(ls + lsa);
} }
// Convert specified SPU LS address to a reference of specified (possibly converted to BE) type // Convert specified SPU LS address to a reference of specified (possibly converted to BE) type
template<typename T> template<typename T>
inline to_be_t<T>& _ref(u32 lsa) to_be_t<T>& _ref(u32 lsa) const
{ {
return *_ptr<T>(lsa); return *_ptr<T>(lsa);
} }
spu_type get_type() const
{
return thread_type;
}
bool read_reg(const u32 addr, u32& value); bool read_reg(const u32 addr, u32& value);
bool write_reg(const u32 addr, const u32 value); bool write_reg(const u32 addr, const u32 value);

View File

@ -108,7 +108,7 @@ void sys_spu_image::free()
} }
} }
void sys_spu_image::deploy(u32 loc, sys_spu_segment* segs, u32 nsegs) void sys_spu_image::deploy(u8* loc, sys_spu_segment* segs, u32 nsegs)
{ {
// Segment info dump // Segment info dump
std::string dump; std::string dump;
@ -129,7 +129,7 @@ void sys_spu_image::deploy(u32 loc, sys_spu_segment* segs, u32 nsegs)
// Hash big-endian values // Hash big-endian values
if (seg.type == SYS_SPU_SEGMENT_TYPE_COPY) if (seg.type == SYS_SPU_SEGMENT_TYPE_COPY)
{ {
std::memcpy(vm::base(loc + seg.ls), vm::base(seg.addr), seg.size); std::memcpy(loc + seg.ls, vm::base(seg.addr), seg.size);
sha1_update(&sha, reinterpret_cast<uchar*>(&seg.size), sizeof(seg.size)); sha1_update(&sha, reinterpret_cast<uchar*>(&seg.size), sizeof(seg.size));
sha1_update(&sha, reinterpret_cast<uchar*>(&seg.ls), sizeof(seg.ls)); sha1_update(&sha, reinterpret_cast<uchar*>(&seg.ls), sizeof(seg.ls));
sha1_update(&sha, vm::_ptr<uchar>(seg.addr), seg.size); sha1_update(&sha, vm::_ptr<uchar>(seg.addr), seg.size);
@ -141,7 +141,7 @@ void sys_spu_image::deploy(u32 loc, sys_spu_segment* segs, u32 nsegs)
spu_log.error("Unaligned SPU FILL type segment (ls=0x%x, size=0x%x)", seg.ls, seg.size); spu_log.error("Unaligned SPU FILL type segment (ls=0x%x, size=0x%x)", seg.ls, seg.size);
} }
std::fill_n(vm::_ptr<u32>(loc + seg.ls), seg.size / 4, seg.addr); std::fill_n(reinterpret_cast<be_t<u32>*>(loc + seg.ls), seg.size / 4, seg.addr);
sha1_update(&sha, reinterpret_cast<uchar*>(&seg.size), sizeof(seg.size)); sha1_update(&sha, reinterpret_cast<uchar*>(&seg.size), sizeof(seg.size));
sha1_update(&sha, reinterpret_cast<uchar*>(&seg.ls), sizeof(seg.ls)); sha1_update(&sha, reinterpret_cast<uchar*>(&seg.ls), sizeof(seg.ls));
sha1_update(&sha, reinterpret_cast<uchar*>(&seg.addr), sizeof(seg.addr)); sha1_update(&sha, reinterpret_cast<uchar*>(&seg.addr), sizeof(seg.addr));
@ -165,12 +165,12 @@ void sys_spu_image::deploy(u32 loc, sys_spu_segment* segs, u32 nsegs)
} }
// Apply the patch // Apply the patch
auto applied = g_fxo->get<patch_engine>()->apply(hash, vm::_ptr<u8>(loc)); auto applied = g_fxo->get<patch_engine>()->apply(hash, loc);
if (!Emu.GetTitleID().empty()) if (!Emu.GetTitleID().empty())
{ {
// Alternative patch // Alternative patch
applied += g_fxo->get<patch_engine>()->apply(Emu.GetTitleID() + '-' + hash, vm::_ptr<u8>(loc)); applied += g_fxo->get<patch_engine>()->apply(Emu.GetTitleID() + '-' + hash, loc);
} }
spu_log.notice("Loaded SPU image: %s (<- %u)%s", hash, applied, dump); spu_log.notice("Loaded SPU image: %s (<- %u)%s", hash, applied, dump);
@ -726,7 +726,7 @@ error_code sys_spu_thread_group_start(ppu_thread& ppu, u32 id)
auto& args = group->args[thread->lv2_id >> 24]; auto& args = group->args[thread->lv2_id >> 24];
auto& img = group->imgs[thread->lv2_id >> 24]; auto& img = group->imgs[thread->lv2_id >> 24];
sys_spu_image::deploy(thread->offset, img.second.data(), img.first.nsegs); sys_spu_image::deploy(thread->ls, img.second.data(), img.first.nsegs);
thread->cpu_init(); thread->cpu_init();
thread->gpr[3] = v128::from64(0, args[0]); thread->gpr[3] = v128::from64(0, args[0]);
@ -1894,7 +1894,7 @@ error_code sys_isolated_spu_create(ppu_thread& ppu, vm::ptr<u32> id, vm::ptr<voi
img.load(obj); img.load(obj);
auto image_info = idm::get<lv2_obj, lv2_spu_image>(img.entry_point); auto image_info = idm::get<lv2_obj, lv2_spu_image>(img.entry_point);
img.deploy(ls_addr, image_info->segs.get_ptr(), image_info->nsegs); img.deploy(thread->ls, image_info->segs.get_ptr(), image_info->nsegs);
thread->write_reg(ls_addr + RAW_SPU_PROB_OFFSET + SPU_NPC_offs, image_info->e_entry); thread->write_reg(ls_addr + RAW_SPU_PROB_OFFSET + SPU_NPC_offs, image_info->e_entry);
verify(HERE), idm::remove_verify<lv2_obj, lv2_spu_image>(img.entry_point, std::move(image_info)); verify(HERE), idm::remove_verify<lv2_obj, lv2_spu_image>(img.entry_point, std::move(image_info));
@ -1910,7 +1910,7 @@ error_code raw_spu_destroy(ppu_thread& ppu, u32 id)
auto thread = idm::get<named_thread<spu_thread>>(idm_id, [](named_thread<spu_thread>& thread) auto thread = idm::get<named_thread<spu_thread>>(idm_id, [](named_thread<spu_thread>& thread)
{ {
if (thread.is_isolated != isolated) if (thread.get_type() != (isolated ? spu_type::isolated : spu_type::raw))
{ {
return false; return false;
} }
@ -2014,7 +2014,7 @@ error_code raw_spu_create_interrupt_tag(u32 id, u32 class_id, u32 hwthread, vm::
auto thread = idm::check_unlocked<named_thread<spu_thread>>(spu_thread::find_raw_spu(id)); auto thread = idm::check_unlocked<named_thread<spu_thread>>(spu_thread::find_raw_spu(id));
if (!thread || *thread == thread_state::aborting || thread->is_isolated != isolated) if (!thread || *thread == thread_state::aborting || thread->get_type() != (isolated ? spu_type::isolated : spu_type::raw))
{ {
error = CELL_ESRCH; error = CELL_ESRCH;
return result; return result;
@ -2070,7 +2070,7 @@ error_code raw_spu_set_int_mask(u32 id, u32 class_id, u64 mask)
const auto thread = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu(id)); const auto thread = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu(id));
if (!thread || thread->is_isolated != isolated) [[unlikely]] if (!thread || thread->get_type() != (isolated ? spu_type::isolated : spu_type::raw)) [[unlikely]]
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -2109,7 +2109,7 @@ error_code raw_spu_set_int_stat(u32 id, u32 class_id, u64 stat)
const auto thread = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu(id)); const auto thread = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu(id));
if (!thread || thread->is_isolated != isolated) [[unlikely]] if (!thread || thread->get_type() != (isolated ? spu_type::isolated : spu_type::raw)) [[unlikely]]
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -2147,7 +2147,7 @@ error_code raw_spu_get_int_control(u32 id, u32 class_id, vm::ptr<u64> value, ato
const auto thread = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu(id)); const auto thread = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu(id));
if (!thread || thread->is_isolated != isolated) [[unlikely]] if (!thread || thread->get_type() != (isolated ? spu_type::isolated : spu_type::raw)) [[unlikely]]
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -2198,7 +2198,7 @@ error_code raw_spu_read_puint_mb(u32 id, vm::ptr<u32> value)
{ {
const auto thread = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu(id)); const auto thread = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu(id));
if (!thread || thread->is_isolated != isolated) [[unlikely]] if (!thread || thread->get_type() != (isolated ? spu_type::isolated : spu_type::raw)) [[unlikely]]
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -2236,7 +2236,7 @@ error_code raw_spu_set_spu_cfg(u32 id, u32 value)
const auto thread = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu(id)); const auto thread = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu(id));
if (!thread || thread->is_isolated != isolated) [[unlikely]] if (!thread || thread->get_type() != (isolated ? spu_type::isolated : spu_type::raw)) [[unlikely]]
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -2269,7 +2269,7 @@ error_code raw_spu_get_spu_cfg(u32 id, vm::ptr<u32> value)
{ {
const auto thread = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu(id)); const auto thread = idm::get<named_thread<spu_thread>>(spu_thread::find_raw_spu(id));
if (!thread || thread->is_isolated != isolated) [[unlikely]] if (!thread || thread->get_type() != (isolated ? spu_type::isolated : spu_type::raw)) [[unlikely]]
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -2311,6 +2311,6 @@ error_code sys_isolated_spu_start(ppu_thread& ppu, u32 id)
} }
// TODO: Can return ESTAT if called twice // TODO: Can return ESTAT if called twice
thread->write_reg(thread->offset + RAW_SPU_PROB_OFFSET + SPU_RunCntl_offs, SPU_RUNCNTL_RUN_REQUEST); thread->write_reg(RAW_SPU_BASE_ADDR + thread->lv2_id * RAW_SPU_OFFSET + RAW_SPU_PROB_OFFSET + SPU_RunCntl_offs, SPU_RUNCNTL_RUN_REQUEST);
return CELL_OK; return CELL_OK;
} }

View File

@ -222,7 +222,7 @@ struct sys_spu_image
void load(const fs::file& stream); void load(const fs::file& stream);
void free(); void free();
static void deploy(u32 loc, sys_spu_segment* segs, u32 nsegs); static void deploy(u8* loc, sys_spu_segment* segs, u32 nsegs);
}; };
enum : u32 enum : u32

View File

@ -63,8 +63,8 @@ void breakpoint_list::AddBreakpoint(u32 pc)
m_breakpoint_handler->AddBreakpoint(pc); m_breakpoint_handler->AddBreakpoint(pc);
const auto cpu = this->cpu.lock(); const auto cpu = this->cpu.lock();
const u32 cpu_offset = cpu->id_type() != 1 ? static_cast<spu_thread&>(*cpu).offset : 0; const auto cpu_offset = cpu->id_type() != 1 ? static_cast<spu_thread&>(*cpu).ls : vm::g_sudo_addr;
m_disasm->offset = vm::_ptr<u8>(cpu_offset); m_disasm->offset = cpu_offset;
m_disasm->disasm(m_disasm->dump_pc = pc); m_disasm->disasm(m_disasm->dump_pc = pc);

View File

@ -92,10 +92,10 @@ void debugger_list::ShowAddress(u32 addr, bool force)
else else
{ {
const bool is_spu = cpu->id_type() != 1; const bool is_spu = cpu->id_type() != 1;
const u32 cpu_offset = is_spu ? static_cast<spu_thread&>(*cpu).offset : 0; const auto cpu_offset = cpu->id_type() != 1 ? static_cast<spu_thread&>(*cpu).ls : vm::g_sudo_addr;
const u32 address_limits = (is_spu ? 0x3fffc : ~3); const u32 address_limits = (is_spu ? 0x3fffc : ~3);
m_pc &= address_limits; m_pc &= address_limits;
m_disasm->offset = vm::get_super_ptr(cpu_offset); m_disasm->offset = cpu_offset;
u32 pc = m_pc; u32 pc = m_pc;
for (uint i = 0, count = 4; i<m_item_count; ++i, pc = (pc + count) & address_limits) for (uint i = 0, count = 4; i<m_item_count; ++i, pc = (pc + count) & address_limits)
@ -116,16 +116,16 @@ void debugger_list::ShowAddress(u32 addr, bool force)
item(i)->setBackground(default_background); item(i)->setBackground(default_background);
} }
if (!vm::check_addr(cpu_offset + pc, 4)) if (!is_spu && !vm::check_addr(pc, 4))
{ {
item(i)->setText((IsBreakpoint(pc) ? ">> " : " ") + qstr(fmt::format("[%08x] ?? ?? ?? ??:", pc))); item(i)->setText((IsBreakpoint(pc) ? ">> " : " ") + qstr(fmt::format("[%08x] ?? ?? ?? ??:", pc)));
count = 4; count = 4;
continue; continue;
} }
if (!is_spu && !vm::check_addr(cpu_offset + pc, 4, vm::page_executable)) if (!is_spu && !vm::check_addr(pc, 4, vm::page_executable))
{ {
const u32 data = *vm::get_super_ptr<atomic_be_t<u32>>(cpu_offset + pc); const u32 data = *vm::get_super_ptr<atomic_be_t<u32>>(pc);
item(i)->setText((IsBreakpoint(pc) ? ">> " : " ") + qstr(fmt::format("[%08x] %02x %02x %02x %02x:", pc, item(i)->setText((IsBreakpoint(pc) ? ">> " : " ") + qstr(fmt::format("[%08x] %02x %02x %02x %02x:", pc,
static_cast<u8>(data >> 24), static_cast<u8>(data >> 24),
static_cast<u8>(data >> 16), static_cast<u8>(data >> 16),

View File

@ -24,8 +24,8 @@ instruction_editor_dialog::instruction_editor_dialog(QWidget *parent, u32 _pc, c
setMinimumSize(300, sizeHint().height()); setMinimumSize(300, sizeHint().height());
const auto cpu = _cpu.get(); const auto cpu = _cpu.get();
m_cpu_offset = cpu->id_type() != 1 ? static_cast<spu_thread&>(*cpu).offset : 0; m_cpu_offset = cpu->id_type() != 1 ? static_cast<spu_thread&>(*cpu).ls : vm::g_sudo_addr;
QString instruction = qstr(fmt::format("%08x", vm::read32(m_cpu_offset + m_pc).value())); QString instruction = qstr(fmt::format("%08x", *reinterpret_cast<be_t<u32>*>(m_cpu_offset + m_pc)));
QVBoxLayout* vbox_panel(new QVBoxLayout()); QVBoxLayout* vbox_panel(new QVBoxLayout());
QHBoxLayout* hbox_panel(new QHBoxLayout()); QHBoxLayout* hbox_panel(new QHBoxLayout());
@ -83,7 +83,7 @@ instruction_editor_dialog::instruction_editor_dialog(QWidget *parent, u32 _pc, c
} }
else if (cpu->id_type() == 1) else if (cpu->id_type() == 1)
{ {
if (!ppu_patch(m_cpu_offset + m_pc, static_cast<u32>(opcode))) if (!ppu_patch(m_pc, static_cast<u32>(opcode)))
{ {
QMessageBox::critical(this, tr("Error"), tr("Failed to patch PPU instruction.")); QMessageBox::critical(this, tr("Error"), tr("Failed to patch PPU instruction."));
return; return;
@ -91,7 +91,8 @@ instruction_editor_dialog::instruction_editor_dialog(QWidget *parent, u32 _pc, c
} }
else else
{ {
vm::write32(m_cpu_offset + m_pc, static_cast<u32>(opcode)); const be_t<u32> swapped{static_cast<u32>(opcode)};
std::memcpy(m_cpu_offset + m_pc, &swapped, 4);
} }
accept(); accept();

View File

@ -15,7 +15,7 @@ class instruction_editor_dialog : public QDialog
private: private:
u32 m_pc; u32 m_pc;
u32 m_cpu_offset; u8* m_cpu_offset;
CPUDisAsm* m_disasm; CPUDisAsm* m_disasm;
QLineEdit* m_instr; QLineEdit* m_instr;
QLabel* m_preview; QLabel* m_preview;

View File

@ -471,18 +471,7 @@ void kernel_explorer::Update()
idm::select<named_thread<spu_thread>>([&](u32 /*id*/, spu_thread& spu) idm::select<named_thread<spu_thread>>([&](u32 /*id*/, spu_thread& spu)
{ {
std::string_view type = "threaded"; add_leaf(find_node(m_tree, additional_nodes::spu_threads), qstr(fmt::format(u8"SPU 0x%07x: “%s”, State: %s, Type: %s", spu.lv2_id, *spu.spu_tname.load(), spu.state.load(), spu.get_type())));
if (spu.is_isolated)
{
type = "isolated";
}
else if (spu.offset >= RAW_SPU_BASE_ADDR)
{
type = "raw";
}
add_leaf(find_node(m_tree, additional_nodes::spu_threads), qstr(fmt::format(u8"SPU 0x%07x: “%s”, State: %s, Type: %s", spu.lv2_id, *spu.spu_tname.load(), spu.state.load(), type)));
}); });
idm::select<lv2_spu_group>([&](u32 id, lv2_spu_group& tg) idm::select<lv2_spu_group>([&](u32 id, lv2_spu_group& tg)