mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-04 11:47:13 +00:00
SPU Thread Group-specific MMIO
LS access, SNR writing
This commit is contained in:
parent
0a35c4f2c4
commit
c9a421f12f
@ -55,7 +55,7 @@ enum
|
||||
MFC_SPU_MAX_QUEUE_SPACE = 0x10,
|
||||
};
|
||||
|
||||
struct DMAC_Queue
|
||||
/*struct DMAC_Queue
|
||||
{
|
||||
bool is_valid;
|
||||
u64 ea;
|
||||
@ -149,13 +149,14 @@ public:
|
||||
{
|
||||
return Memory.Read32(m_addr);
|
||||
}
|
||||
};
|
||||
};*/
|
||||
|
||||
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;
|
||||
|
||||
/*//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 proxy_pos;
|
||||
long queue_lock;
|
||||
@ -194,18 +195,6 @@ struct DMAC
|
||||
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);
|
||||
|
||||
return MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL;
|
||||
@ -230,10 +219,10 @@ struct DMAC
|
||||
ClearCmd();
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
};
|
||||
|
||||
struct MFC
|
||||
/*struct MFC
|
||||
{
|
||||
SPUReg<1> MFC_LSA;
|
||||
SPUReg<1> MFC_EAH;
|
||||
@ -299,4 +288,4 @@ struct MFC
|
||||
MFC_QStatus.SetValue(mask);
|
||||
}
|
||||
}
|
||||
};
|
||||
};*/
|
||||
|
@ -283,7 +283,7 @@ void RawSPUThread::Task()
|
||||
continue;
|
||||
}
|
||||
|
||||
dmac.DoCmd();
|
||||
//dmac.DoCmd();
|
||||
|
||||
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);
|
||||
|
||||
group = nullptr;
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
@ -46,10 +48,10 @@ void SPUThread::InitRegs()
|
||||
cfg.Reset();
|
||||
|
||||
dmac.ls_offset = m_offset;
|
||||
dmac.proxy_pos = 0;
|
||||
/*dmac.proxy_pos = 0;
|
||||
dmac.queue_pos = 0;
|
||||
dmac.proxy_lock = 0;
|
||||
dmac.queue_lock = 0;
|
||||
dmac.queue_lock = 0;*/
|
||||
|
||||
SPU.RunCntl.SetValue(SPU_RUNCNTL_STOP);
|
||||
SPU.Status.SetValue(SPU_STATUS_RUNNING);
|
||||
|
@ -119,6 +119,15 @@ enum
|
||||
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
|
||||
//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
|
||||
@ -278,6 +287,7 @@ public:
|
||||
|
||||
EventPort SPUPs[64]; // SPU Thread Event Ports
|
||||
EventManager SPUQs; // SPU Queue Mapping
|
||||
SpuGroupInfo* group; // associated SPU Thread Group (null for raw spu)
|
||||
|
||||
template<size_t _max_count>
|
||||
class Channel
|
||||
@ -512,6 +522,18 @@ public:
|
||||
Channel<1> SNR[2];
|
||||
} 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;
|
||||
|
||||
union
|
||||
@ -522,6 +544,82 @@ public:
|
||||
|
||||
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)
|
||||
{
|
||||
u32 list_addr = ea & 0x3ffff;
|
||||
@ -549,7 +647,7 @@ public:
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
break;
|
||||
@ -606,7 +704,7 @@ public:
|
||||
if (op & MFC_PUT_CMD)
|
||||
{
|
||||
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) ||
|
||||
(ea + size > reservation.addr && ea <= reservation.addr + reservation.size))
|
||||
{
|
||||
@ -615,7 +713,7 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
MFCArgs.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size));
|
||||
MFCArgs.CMDStatus.SetValue(dmacCmd(cmd, tag, lsa, ea, size));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -650,7 +748,7 @@ public:
|
||||
reservation.owner = lock.tid;
|
||||
reservation.addr = ea;
|
||||
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);
|
||||
}
|
||||
else if (op == MFC_PUTLLC_CMD) // store conditional
|
||||
@ -660,7 +758,7 @@ public:
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
@ -677,7 +775,7 @@ public:
|
||||
else // store unconditional
|
||||
{
|
||||
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)
|
||||
{
|
||||
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();
|
||||
|
||||
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",
|
||||
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;
|
||||
}
|
||||
|
||||
if ((*(SPUThread*)thr).cfg.value & ((u64)1<<number))
|
||||
{ //logical OR
|
||||
(*(SPUThread*)thr).SPU.SNR[number].PushUncond_OR(value);
|
||||
}
|
||||
else
|
||||
{ //overwrite
|
||||
(*(SPUThread*)thr).SPU.SNR[number].PushUncond(value);
|
||||
}
|
||||
(*(SPUThread*)thr).WriteSNR(number, value);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user