mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-09 00:11:24 +12:00
SPU Thread Group-specific MMIO
LS access, SNR writing
This commit is contained in:
parent
0a35c4f2c4
commit
c9a421f12f
5 changed files with 119 additions and 36 deletions
|
@ -55,7 +55,7 @@ enum
|
||||||
MFC_SPU_MAX_QUEUE_SPACE = 0x10,
|
MFC_SPU_MAX_QUEUE_SPACE = 0x10,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DMAC_Queue
|
/*struct DMAC_Queue
|
||||||
{
|
{
|
||||||
bool is_valid;
|
bool is_valid;
|
||||||
u64 ea;
|
u64 ea;
|
||||||
|
@ -149,13 +149,14 @@ public:
|
||||||
{
|
{
|
||||||
return Memory.Read32(m_addr);
|
return Memory.Read32(m_addr);
|
||||||
}
|
}
|
||||||
};
|
};*/
|
||||||
|
|
||||||
struct DMAC
|
struct DMAC
|
||||||
{
|
{
|
||||||
//DMAC_Queue queue[MFC_SPU_MAX_QUEUE_SPACE]; //not used yet
|
|
||||||
DMAC_Proxy proxy[MFC_PPU_MAX_QUEUE_SPACE+MFC_SPU_MAX_QUEUE_SPACE]; //temporarily 24
|
|
||||||
u64 ls_offset;
|
u64 ls_offset;
|
||||||
|
|
||||||
|
/*//DMAC_Queue queue[MFC_SPU_MAX_QUEUE_SPACE]; //not used yet
|
||||||
|
DMAC_Proxy proxy[MFC_PPU_MAX_QUEUE_SPACE+MFC_SPU_MAX_QUEUE_SPACE]; //temporarily 24
|
||||||
u32 queue_pos;
|
u32 queue_pos;
|
||||||
u32 proxy_pos;
|
u32 proxy_pos;
|
||||||
long queue_lock;
|
long queue_lock;
|
||||||
|
@ -194,18 +195,6 @@ struct DMAC
|
||||||
return MFC_PPU_DMA_QUEUE_FULL;
|
return MFC_PPU_DMA_QUEUE_FULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* while (std::atomic_exchange(&proxy_lock, 1));
|
|
||||||
_mm_lfence();
|
|
||||||
DMAC_Proxy& p = proxy[proxy_pos];
|
|
||||||
p.cmd = cmd;
|
|
||||||
p.tag = tag;
|
|
||||||
p.lsa = lsa;
|
|
||||||
p.ea = ea;
|
|
||||||
p.size = size;
|
|
||||||
_mm_sfence(); //for DoCmd()
|
|
||||||
proxy_pos++;
|
|
||||||
_mm_sfence();
|
|
||||||
proxy_lock = 0; */
|
|
||||||
ProcessCmd(cmd, tag, lsa, ea, size);
|
ProcessCmd(cmd, tag, lsa, ea, size);
|
||||||
|
|
||||||
return MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL;
|
return MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL;
|
||||||
|
@ -230,10 +219,10 @@ struct DMAC
|
||||||
ClearCmd();
|
ClearCmd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MFC
|
/*struct MFC
|
||||||
{
|
{
|
||||||
SPUReg<1> MFC_LSA;
|
SPUReg<1> MFC_LSA;
|
||||||
SPUReg<1> MFC_EAH;
|
SPUReg<1> MFC_EAH;
|
||||||
|
@ -299,4 +288,4 @@ struct MFC
|
||||||
MFC_QStatus.SetValue(mask);
|
MFC_QStatus.SetValue(mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};*/
|
||||||
|
|
|
@ -283,7 +283,7 @@ void RawSPUThread::Task()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
dmac.DoCmd();
|
//dmac.DoCmd();
|
||||||
|
|
||||||
if(SPU.RunCntl.GetValue() != SPU_RUNCNTL_RUNNABLE)
|
if(SPU.RunCntl.GetValue() != SPU_RUNCNTL_RUNNABLE)
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,6 +20,8 @@ SPUThread::SPUThread(CPUThreadType type) : PPCThread(type)
|
||||||
{
|
{
|
||||||
assert(type == CPU_THREAD_SPU || type == CPU_THREAD_RAW_SPU);
|
assert(type == CPU_THREAD_SPU || type == CPU_THREAD_RAW_SPU);
|
||||||
|
|
||||||
|
group = nullptr;
|
||||||
|
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,10 +48,10 @@ void SPUThread::InitRegs()
|
||||||
cfg.Reset();
|
cfg.Reset();
|
||||||
|
|
||||||
dmac.ls_offset = m_offset;
|
dmac.ls_offset = m_offset;
|
||||||
dmac.proxy_pos = 0;
|
/*dmac.proxy_pos = 0;
|
||||||
dmac.queue_pos = 0;
|
dmac.queue_pos = 0;
|
||||||
dmac.proxy_lock = 0;
|
dmac.proxy_lock = 0;
|
||||||
dmac.queue_lock = 0;
|
dmac.queue_lock = 0;*/
|
||||||
|
|
||||||
SPU.RunCntl.SetValue(SPU_RUNCNTL_STOP);
|
SPU.RunCntl.SetValue(SPU_RUNCNTL_STOP);
|
||||||
SPU.Status.SetValue(SPU_STATUS_RUNNING);
|
SPU.Status.SetValue(SPU_STATUS_RUNNING);
|
||||||
|
|
|
@ -119,6 +119,15 @@ enum
|
||||||
SPU_STATUS_SINGLE_STEP = 0x10,
|
SPU_STATUS_SINGLE_STEP = 0x10,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum : u32
|
||||||
|
{
|
||||||
|
SYS_SPU_THREAD_BASE_LOW = 0xf0000000,
|
||||||
|
SYS_SPU_THREAD_BASE_MASK = 0xfffffff,
|
||||||
|
SYS_SPU_THREAD_OFFSET = 0x00100000,
|
||||||
|
SYS_SPU_THREAD_SNR1 = 0x05400c,
|
||||||
|
SYS_SPU_THREAD_SNR2 = 0x05C00c,
|
||||||
|
};
|
||||||
|
|
||||||
//Floating point status and control register. Unsure if this is one of the GPRs or SPRs
|
//Floating point status and control register. Unsure if this is one of the GPRs or SPRs
|
||||||
//Is 128 bits, but bits 0-19, 24-28, 32-49, 56-60, 64-81, 88-92, 96-115, 120-124 are unused
|
//Is 128 bits, but bits 0-19, 24-28, 32-49, 56-60, 64-81, 88-92, 96-115, 120-124 are unused
|
||||||
class FPSCR
|
class FPSCR
|
||||||
|
@ -278,6 +287,7 @@ public:
|
||||||
|
|
||||||
EventPort SPUPs[64]; // SPU Thread Event Ports
|
EventPort SPUPs[64]; // SPU Thread Event Ports
|
||||||
EventManager SPUQs; // SPU Queue Mapping
|
EventManager SPUQs; // SPU Queue Mapping
|
||||||
|
SpuGroupInfo* group; // associated SPU Thread Group (null for raw spu)
|
||||||
|
|
||||||
template<size_t _max_count>
|
template<size_t _max_count>
|
||||||
class Channel
|
class Channel
|
||||||
|
@ -512,6 +522,18 @@ public:
|
||||||
Channel<1> SNR[2];
|
Channel<1> SNR[2];
|
||||||
} SPU;
|
} SPU;
|
||||||
|
|
||||||
|
void WriteSNR(bool number, u32 value)
|
||||||
|
{
|
||||||
|
if (cfg.value & ((u64)1 << (u64)number))
|
||||||
|
{
|
||||||
|
SPU.SNR[number].PushUncond_OR(value); // logical OR
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SPU.SNR[number].PushUncond(value); // overwrite
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
u32 LSA;
|
u32 LSA;
|
||||||
|
|
||||||
union
|
union
|
||||||
|
@ -522,6 +544,82 @@ public:
|
||||||
|
|
||||||
DMAC dmac;
|
DMAC dmac;
|
||||||
|
|
||||||
|
bool ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
|
||||||
|
{
|
||||||
|
if (cmd & (MFC_BARRIER_MASK | MFC_FENCE_MASK)) _mm_mfence();
|
||||||
|
|
||||||
|
if ((ea & 0xf0000000) == SYS_SPU_THREAD_BASE_LOW)
|
||||||
|
{
|
||||||
|
if (group)
|
||||||
|
{
|
||||||
|
// SPU Thread Group MMIO (LS and SNR)
|
||||||
|
u32 num = (ea & SYS_SPU_THREAD_BASE_MASK) / SYS_SPU_THREAD_OFFSET; // thread number in group
|
||||||
|
if (num >= group->list.GetCount() || !group->list[num])
|
||||||
|
{
|
||||||
|
ConLog.Error("DMAC::ProcessCmd(): SPU Thread Group MMIO Access (ea=0x%llx): invalid thread", ea);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPUThread* spu = (SPUThread*)Emu.GetCPU().GetThread(group->list[num]);
|
||||||
|
|
||||||
|
u32 addr = (ea & SYS_SPU_THREAD_BASE_MASK) % SYS_SPU_THREAD_OFFSET;
|
||||||
|
if ((addr <= 0x3ffff) && (addr + size <= 0x40000))
|
||||||
|
{
|
||||||
|
// LS access
|
||||||
|
ea = spu->dmac.ls_offset + addr;
|
||||||
|
}
|
||||||
|
else if ((cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK)) == MFC_PUT_CMD &&
|
||||||
|
size == 4 && (addr == SYS_SPU_THREAD_SNR1 || addr == SYS_SPU_THREAD_SNR2))
|
||||||
|
{
|
||||||
|
spu->WriteSNR(SYS_SPU_THREAD_SNR2 == addr, Memory.Read32(dmac.ls_offset + lsa));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ConLog.Error("DMAC::ProcessCmd(): SPU Thread Group MMIO Access (ea=0x%llx, size=%d, cmd=0x%x): invalid command", ea, size, cmd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ConLog.Error("DMAC::ProcessCmd(): SPU Thread Group MMIO Access (ea=0x%llx): group not set", ea);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK))
|
||||||
|
{
|
||||||
|
case MFC_PUT_CMD:
|
||||||
|
{
|
||||||
|
return Memory.Copy(ea, dmac.ls_offset + lsa, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
case MFC_GET_CMD:
|
||||||
|
{
|
||||||
|
return Memory.Copy(dmac.ls_offset + lsa, ea, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
ConLog.Error("DMAC::ProcessCmd(): Unknown DMA cmd.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 dmacCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
|
||||||
|
{
|
||||||
|
/*if(proxy_pos >= MFC_PPU_MAX_QUEUE_SPACE)
|
||||||
|
{
|
||||||
|
return MFC_PPU_DMA_QUEUE_FULL;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
if (ProcessCmd(cmd, tag, lsa, ea, size))
|
||||||
|
return MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL;
|
||||||
|
else
|
||||||
|
return MFC_PPU_DMA_CMD_SEQUENCE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
void ListCmd(u32 lsa, u64 ea, u16 tag, u16 size, u32 cmd, MFCReg& MFCArgs)
|
void ListCmd(u32 lsa, u64 ea, u16 tag, u16 size, u32 cmd, MFCReg& MFCArgs)
|
||||||
{
|
{
|
||||||
u32 list_addr = ea & 0x3ffff;
|
u32 list_addr = ea & 0x3ffff;
|
||||||
|
@ -549,7 +647,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 addr = rec->ea;
|
u32 addr = rec->ea;
|
||||||
result = dmac.Cmd(cmd, tag, lsa | (addr & 0xf), addr, size);
|
result = dmacCmd(cmd, tag, lsa | (addr & 0xf), addr, size);
|
||||||
if (result == MFC_PPU_DMA_CMD_SEQUENCE_ERROR)
|
if (result == MFC_PPU_DMA_CMD_SEQUENCE_ERROR)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
@ -606,7 +704,7 @@ public:
|
||||||
if (op & MFC_PUT_CMD)
|
if (op & MFC_PUT_CMD)
|
||||||
{
|
{
|
||||||
SMutexLocker lock(reservation.mutex); // should be removed
|
SMutexLocker lock(reservation.mutex); // should be removed
|
||||||
MFCArgs.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size));
|
MFCArgs.CMDStatus.SetValue(dmacCmd(cmd, tag, lsa, ea, size));
|
||||||
if ((reservation.addr + reservation.size > ea && reservation.addr <= ea + size) ||
|
if ((reservation.addr + reservation.size > ea && reservation.addr <= ea + size) ||
|
||||||
(ea + size > reservation.addr && ea <= reservation.addr + reservation.size))
|
(ea + size > reservation.addr && ea <= reservation.addr + reservation.size))
|
||||||
{
|
{
|
||||||
|
@ -615,7 +713,7 @@ public:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MFCArgs.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size));
|
MFCArgs.CMDStatus.SetValue(dmacCmd(cmd, tag, lsa, ea, size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -650,7 +748,7 @@ public:
|
||||||
reservation.owner = lock.tid;
|
reservation.owner = lock.tid;
|
||||||
reservation.addr = ea;
|
reservation.addr = ea;
|
||||||
reservation.size = 128;
|
reservation.size = 128;
|
||||||
dmac.ProcessCmd(MFC_GET_CMD, tag, lsa, ea, 128);
|
ProcessCmd(MFC_GET_CMD, tag, lsa, ea, 128);
|
||||||
Prxy.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS);
|
Prxy.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS);
|
||||||
}
|
}
|
||||||
else if (op == MFC_PUTLLC_CMD) // store conditional
|
else if (op == MFC_PUTLLC_CMD) // store conditional
|
||||||
|
@ -660,7 +758,7 @@ public:
|
||||||
{
|
{
|
||||||
if (reservation.addr == ea && reservation.size == 128)
|
if (reservation.addr == ea && reservation.size == 128)
|
||||||
{
|
{
|
||||||
dmac.ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128);
|
ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128);
|
||||||
Prxy.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS);
|
Prxy.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -677,7 +775,7 @@ public:
|
||||||
else // store unconditional
|
else // store unconditional
|
||||||
{
|
{
|
||||||
SMutexLocker lock(reservation.mutex);
|
SMutexLocker lock(reservation.mutex);
|
||||||
dmac.ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128);
|
ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128);
|
||||||
if (op == MFC_PUTLLUC_CMD)
|
if (op == MFC_PUTLLUC_CMD)
|
||||||
{
|
{
|
||||||
Prxy.AtomicStat.PushUncond(MFC_PUTLLUC_SUCCESS);
|
Prxy.AtomicStat.PushUncond(MFC_PUTLLUC_SUCCESS);
|
||||||
|
|
|
@ -120,6 +120,7 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t<
|
||||||
new_thread.Run();
|
new_thread.Run();
|
||||||
|
|
||||||
thread = group_info->list[spu_num] = new_thread.GetId();
|
thread = group_info->list[spu_num] = new_thread.GetId();
|
||||||
|
(*(SPUThread*)&new_thread).group = group_info;
|
||||||
|
|
||||||
sc_spu.Warning("*** New SPU Thread [%s] (img_offset=0x%x, ls_offset=0x%x, ep=0x%x, a1=0x%llx, a2=0x%llx, a3=0x%llx, a4=0x%llx): id=%d",
|
sc_spu.Warning("*** New SPU Thread [%s] (img_offset=0x%x, ls_offset=0x%x, ep=0x%x, a1=0x%llx, a2=0x%llx, a3=0x%llx, a4=0x%llx): id=%d",
|
||||||
wxString(name).wx_str(), (u32)img->segs_addr, ((SPUThread&)new_thread).dmac.ls_offset, spu_ep, a1, a2, a3, a4, thread.GetValue());
|
wxString(name).wx_str(), (u32)img->segs_addr, ((SPUThread&)new_thread).dmac.ls_offset, spu_ep, a1, a2, a3, a4, thread.GetValue());
|
||||||
|
@ -500,14 +501,7 @@ int sys_spu_thread_write_snr(u32 id, u32 number, u32 value)
|
||||||
return CELL_EINVAL;
|
return CELL_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*(SPUThread*)thr).cfg.value & ((u64)1<<number))
|
(*(SPUThread*)thr).WriteSNR(number, value);
|
||||||
{ //logical OR
|
|
||||||
(*(SPUThread*)thr).SPU.SNR[number].PushUncond_OR(value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ //overwrite
|
|
||||||
(*(SPUThread*)thr).SPU.SNR[number].PushUncond(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue