mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-14 01:27:00 +00:00
Small SPU cleanup
This commit is contained in:
parent
e3fbfc4bda
commit
fa5311718e
@ -12,7 +12,7 @@ struct reservation_struct
|
||||
// std::mutex doesn't work because it probably wakes up waiting threads in the most unwanted order
|
||||
// and doesn't give a chance to finish some work before losing the reservation
|
||||
u32 owner; // id of thread that got reservation
|
||||
u32 addr;
|
||||
u64 addr;
|
||||
u32 size;
|
||||
u32 data32;
|
||||
u64 data64;
|
||||
|
@ -60,237 +60,7 @@ enum
|
||||
MFC_SPU_MAX_QUEUE_SPACE = 0x10,
|
||||
};
|
||||
|
||||
/*struct DMAC_Queue
|
||||
{
|
||||
bool is_valid;
|
||||
u64 ea;
|
||||
u32 lsa;
|
||||
u16 size;
|
||||
u32 op;
|
||||
u8 tag;
|
||||
u8 rt;
|
||||
u16 list_addr;
|
||||
u16 list_size;
|
||||
u32 dep_state;
|
||||
u32 cmd;
|
||||
u32 dep_type;
|
||||
};
|
||||
|
||||
struct DMAC_Proxy
|
||||
{
|
||||
u64 ea;
|
||||
u32 lsa;
|
||||
u16 size;
|
||||
u32 op;
|
||||
u8 tag;
|
||||
u8 rt;
|
||||
u16 list_addr;
|
||||
u16 list_size;
|
||||
u32 dep_state;
|
||||
u32 cmd;
|
||||
u32 dep_type;
|
||||
};
|
||||
|
||||
template<size_t _max_count>
|
||||
class SPUReg
|
||||
{
|
||||
u64 m_addr;
|
||||
u32 m_pos;
|
||||
|
||||
public:
|
||||
static const size_t max_count = _max_count;
|
||||
static const size_t size = max_count * 4;
|
||||
|
||||
SPUReg()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
m_pos = 0;
|
||||
}
|
||||
|
||||
void SetAddr(u64 addr)
|
||||
{
|
||||
m_addr = addr;
|
||||
}
|
||||
|
||||
u64 GetAddr() const
|
||||
{
|
||||
return m_addr;
|
||||
}
|
||||
|
||||
__forceinline bool Pop(u32& res)
|
||||
{
|
||||
if(!m_pos) return false;
|
||||
res = Memory.Read32(m_addr + m_pos--);
|
||||
return true;
|
||||
}
|
||||
|
||||
__forceinline bool Push(u32 value)
|
||||
{
|
||||
if(m_pos >= max_count) return false;
|
||||
Memory.Write32(m_addr + m_pos++, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
u32 GetCount() const
|
||||
{
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
u32 GetFreeCount() const
|
||||
{
|
||||
return max_count - m_pos;
|
||||
}
|
||||
|
||||
void SetValue(u32 value)
|
||||
{
|
||||
Memory.Write32(m_addr, value);
|
||||
}
|
||||
|
||||
u32 GetValue() const
|
||||
{
|
||||
return Memory.Read32(m_addr);
|
||||
}
|
||||
};*/
|
||||
|
||||
struct DMAC
|
||||
{
|
||||
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;
|
||||
volatile std::atomic<int> proxy_lock;
|
||||
|
||||
bool ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
|
||||
{
|
||||
//returns true if the command should be deleted from the queue
|
||||
if (cmd & (MFC_BARRIER_MASK | MFC_FENCE_MASK)) _mm_mfence();
|
||||
|
||||
switch(cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK))
|
||||
{
|
||||
case MFC_PUT_CMD:
|
||||
Memory.Copy(ea, ls_offset + lsa, size);
|
||||
return true;
|
||||
|
||||
case MFC_GET_CMD:
|
||||
Memory.Copy(ls_offset + lsa, ea, size);
|
||||
return true;
|
||||
|
||||
default:
|
||||
LOG_ERROR(HLE, "DMAC::ProcessCmd(): Unknown DMA cmd.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
u32 Cmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
|
||||
{
|
||||
if(!Memory.IsGoodAddr(ls_offset + lsa, size) || !Memory.IsGoodAddr(ea, size))
|
||||
{
|
||||
return MFC_PPU_DMA_CMD_SEQUENCE_ERROR;
|
||||
}
|
||||
|
||||
if(proxy_pos >= MFC_PPU_MAX_QUEUE_SPACE)
|
||||
{
|
||||
return MFC_PPU_DMA_QUEUE_FULL;
|
||||
}
|
||||
|
||||
ProcessCmd(cmd, tag, lsa, ea, size);
|
||||
|
||||
return MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL;
|
||||
}
|
||||
|
||||
void ClearCmd()
|
||||
{
|
||||
while (std::atomic_exchange(&proxy_lock, 1));
|
||||
_mm_lfence();
|
||||
memcpy(proxy, proxy + 1, --proxy_pos * sizeof(DMAC_Proxy));
|
||||
_mm_sfence();
|
||||
proxy_lock = 0; //release lock
|
||||
}
|
||||
|
||||
void DoCmd()
|
||||
{
|
||||
if(proxy_pos)
|
||||
{
|
||||
const DMAC_Proxy& p = proxy[0];
|
||||
if (ProcessCmd(p.cmd, p.tag, p.lsa, p.ea, p.size))
|
||||
{
|
||||
ClearCmd();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
};
|
||||
|
||||
/*struct MFC
|
||||
{
|
||||
SPUReg<1> MFC_LSA;
|
||||
SPUReg<1> MFC_EAH;
|
||||
SPUReg<1> MFC_EAL;
|
||||
SPUReg<1> MFC_Size_Tag;
|
||||
SPUReg<1> MFC_CMDStatus;
|
||||
SPUReg<1> MFC_QStatus;
|
||||
SPUReg<1> Prxy_QueryType;
|
||||
SPUReg<1> Prxy_QueryMask;
|
||||
SPUReg<1> Prxy_TagStatus;
|
||||
SPUReg<1> SPU_Out_MBox;
|
||||
SPUReg<4> SPU_In_MBox;
|
||||
SPUReg<1> SPU_MBox_Status;
|
||||
SPUReg<1> SPU_RunCntl;
|
||||
SPUReg<1> SPU_Status;
|
||||
SPUReg<1> SPU_NPC;
|
||||
SPUReg<1> SPU_RdSigNotify1;
|
||||
SPUReg<1> SPU_RdSigNotify2;
|
||||
|
||||
DMAC dmac;
|
||||
|
||||
void Handle()
|
||||
{
|
||||
u32 cmd = MFC_CMDStatus.GetValue();
|
||||
|
||||
if(cmd)
|
||||
{
|
||||
u16 op = cmd & MFC_MASK_CMD;
|
||||
|
||||
switch(op)
|
||||
{
|
||||
case MFC_PUT_CMD:
|
||||
case MFC_GET_CMD:
|
||||
{
|
||||
u32 lsa = MFC_LSA.GetValue();
|
||||
u64 ea = (u64)MFC_EAL.GetValue() | ((u64)MFC_EAH.GetValue() << 32);
|
||||
u32 size_tag = MFC_Size_Tag.GetValue();
|
||||
u16 tag = (u16)size_tag;
|
||||
u16 size = size_tag >> 16;
|
||||
|
||||
LOG_WARNING(HLE, "RawSPU DMA %s:", op == MFC_PUT_CMD ? "PUT" : "GET");
|
||||
LOG_WARNING(HLE, "*** lsa = 0x%x", lsa);
|
||||
LOG_WARNING(HLE, "*** ea = 0x%llx", ea);
|
||||
LOG_WARNING(HLE, "*** tag = 0x%x", tag);
|
||||
LOG_WARNING(HLE, "*** size = 0x%x", size);
|
||||
LOG_WARNING(HLE, " ");
|
||||
|
||||
MFC_CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_ERROR(HLE, "Unknown MFC cmd. (opcode=0x%x, cmd=0x%x)", op, cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(Prxy_QueryType.GetValue() == 2)
|
||||
{
|
||||
Prxy_QueryType.SetValue(0);
|
||||
u32 mask = Prxy_QueryMask.GetValue();
|
||||
//
|
||||
MFC_QStatus.SetValue(mask);
|
||||
}
|
||||
}
|
||||
};*/
|
||||
|
@ -579,7 +579,7 @@ public:
|
||||
|
||||
#define LOG_DMAC(type, text) type(Log::SPU, "DMAC::ProcessCmd(cmd=0x%x, tag=0x%x, lsa=0x%x, ea=0x%llx, size=0x%x): " text, cmd, tag, lsa, ea, size)
|
||||
|
||||
bool ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
|
||||
void ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
|
||||
{
|
||||
if (cmd & (MFC_BARRIER_MASK | MFC_FENCE_MASK)) _mm_mfence();
|
||||
|
||||
@ -588,7 +588,8 @@ public:
|
||||
if (ea >= 0x100000000)
|
||||
{
|
||||
LOG_DMAC(LOG_ERROR, "Invalid external address");
|
||||
return false;
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
else if (group)
|
||||
{
|
||||
@ -597,7 +598,8 @@ public:
|
||||
if (num >= group->list.size() || !group->list[num])
|
||||
{
|
||||
LOG_DMAC(LOG_ERROR, "Invalid thread (SPU Thread Group MMIO)");
|
||||
return false;
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
|
||||
SPUThread* spu = (SPUThread*)Emu.GetCPU().GetThread(group->list[num]);
|
||||
@ -611,18 +613,20 @@ public:
|
||||
else if ((cmd & 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;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DMAC(LOG_ERROR, "Invalid register (SPU Thread Group MMIO)");
|
||||
return false;
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DMAC(LOG_ERROR, "Thread group not set (SPU Thread Group MMIO)");
|
||||
return false;
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (ea >= RAW_SPU_BASE_ADDR && size == 4)
|
||||
@ -632,19 +636,20 @@ public:
|
||||
case MFC_PUT_CMD:
|
||||
{
|
||||
Memory.Write32(ea, ReadLS32(lsa));
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
case MFC_GET_CMD:
|
||||
{
|
||||
WriteLS32(lsa, Memory.Read32(ea));
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
LOG_DMAC(LOG_ERROR, "Unknown DMA command");
|
||||
return false;
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -653,53 +658,27 @@ public:
|
||||
{
|
||||
case MFC_PUT_CMD:
|
||||
{
|
||||
if (Memory.Copy(ea, dmac.ls_offset + lsa, size))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DMAC(LOG_ERROR, "PUT* cmd failed");
|
||||
return false; // TODO: page fault (?)
|
||||
}
|
||||
memcpy(Memory + ea, Memory + dmac.ls_offset + lsa, size);
|
||||
return;
|
||||
}
|
||||
|
||||
case MFC_GET_CMD:
|
||||
{
|
||||
if (Memory.Copy(dmac.ls_offset + lsa, ea, size))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DMAC(LOG_ERROR, "GET* cmd failed");
|
||||
return false; // TODO: page fault (?)
|
||||
}
|
||||
memcpy(Memory + dmac.ls_offset + lsa, Memory + ea, size);
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
LOG_DMAC(LOG_ERROR, "Unknown DMA command");
|
||||
return false; // ???
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef LOG_CMD
|
||||
|
||||
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;
|
||||
@ -713,7 +692,7 @@ public:
|
||||
be_t<u32> ea; // External Address Low
|
||||
};
|
||||
|
||||
u32 result = MFC_PPU_DMA_CMD_SEQUENCE_ERROR;
|
||||
u32 result = MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL;
|
||||
|
||||
for (u32 i = 0; i < list_size; i++)
|
||||
{
|
||||
@ -723,15 +702,12 @@ public:
|
||||
if (size < 16 && size != 1 && size != 2 && size != 4 && size != 8)
|
||||
{
|
||||
LOG_ERROR(Log::SPU, "DMA List: invalid transfer size(%d)", size);
|
||||
return;
|
||||
result = MFC_PPU_DMA_CMD_SEQUENCE_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
u32 addr = rec->ea;
|
||||
result = dmacCmd(cmd, tag, lsa | (addr & 0xf), addr, size);
|
||||
if (result == MFC_PPU_DMA_CMD_SEQUENCE_ERROR)
|
||||
{
|
||||
break;
|
||||
}
|
||||
ProcessCmd(cmd, tag, lsa | (addr & 0xf), addr, size);
|
||||
|
||||
if (Ini.HLELogging.GetValue() || rec->s)
|
||||
LOG_NOTICE(Log::SPU, "*** list element(%d/%d): s = 0x%x, ts = 0x%x, low ea = 0x%x (lsa = 0x%x)",
|
||||
@ -746,6 +722,8 @@ public:
|
||||
if (StallList[tag].MFCArgs)
|
||||
{
|
||||
LOG_ERROR(Log::SPU, "DMA List: existing stalled list found (tag=%d)", tag);
|
||||
result = MFC_PPU_DMA_CMD_SEQUENCE_ERROR;
|
||||
break;
|
||||
}
|
||||
StallList[tag].MFCArgs = &MFCArgs;
|
||||
StallList[tag].cmd = cmd;
|
||||
@ -753,7 +731,7 @@ public:
|
||||
StallList[tag].lsa = lsa;
|
||||
StallList[tag].size = (list_size - i - 1) * 8;
|
||||
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -784,7 +762,8 @@ public:
|
||||
(op & MFC_FENCE_MASK ? "F" : ""),
|
||||
lsa, ea, tag, size, cmd);
|
||||
|
||||
MFCArgs.CMDStatus.SetValue(dmacCmd(cmd, tag, lsa, ea, size));
|
||||
ProcessCmd(cmd, tag, lsa, ea, size);
|
||||
MFCArgs.CMDStatus.SetValue(MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -871,21 +850,6 @@ public:
|
||||
{
|
||||
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE);
|
||||
}
|
||||
/*u32 last_d = last_q * 2;
|
||||
if (buf[last]._u32[last_d] == reservation.data[last]._u32[last_d] && buf[last]._u32[last_d+1] != reservation.data[last]._u32[last_d+1])
|
||||
{
|
||||
last_d++;
|
||||
}
|
||||
else if (buf[last]._u32[last_d+1] == reservation.data[last]._u32[last_d+1])
|
||||
{
|
||||
last_d;
|
||||
}
|
||||
else // full 64 bit
|
||||
{
|
||||
LOG_ERROR(Log::SPU, "MFC_PUTLLC_CMD: TODO: 64bit compare and swap");
|
||||
Emu.Pause();
|
||||
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
else
|
||||
|
Loading…
x
Reference in New Issue
Block a user