mirror of https://github.com/RPCS3/rpcs3.git
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
|
// 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
|
// and doesn't give a chance to finish some work before losing the reservation
|
||||||
u32 owner; // id of thread that got reservation
|
u32 owner; // id of thread that got reservation
|
||||||
u32 addr;
|
u64 addr;
|
||||||
u32 size;
|
u32 size;
|
||||||
u32 data32;
|
u32 data32;
|
||||||
u64 data64;
|
u64 data64;
|
||||||
|
|
|
@ -60,237 +60,7 @@ enum
|
||||||
MFC_SPU_MAX_QUEUE_SPACE = 0x10,
|
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
|
struct DMAC
|
||||||
{
|
{
|
||||||
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 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)
|
#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();
|
if (cmd & (MFC_BARRIER_MASK | MFC_FENCE_MASK)) _mm_mfence();
|
||||||
|
|
||||||
|
@ -588,7 +588,8 @@ public:
|
||||||
if (ea >= 0x100000000)
|
if (ea >= 0x100000000)
|
||||||
{
|
{
|
||||||
LOG_DMAC(LOG_ERROR, "Invalid external address");
|
LOG_DMAC(LOG_ERROR, "Invalid external address");
|
||||||
return false;
|
Emu.Pause();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else if (group)
|
else if (group)
|
||||||
{
|
{
|
||||||
|
@ -597,7 +598,8 @@ public:
|
||||||
if (num >= group->list.size() || !group->list[num])
|
if (num >= group->list.size() || !group->list[num])
|
||||||
{
|
{
|
||||||
LOG_DMAC(LOG_ERROR, "Invalid thread (SPU Thread Group MMIO)");
|
LOG_DMAC(LOG_ERROR, "Invalid thread (SPU Thread Group MMIO)");
|
||||||
return false;
|
Emu.Pause();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SPUThread* spu = (SPUThread*)Emu.GetCPU().GetThread(group->list[num]);
|
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))
|
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));
|
spu->WriteSNR(SYS_SPU_THREAD_SNR2 == addr, Memory.Read32(dmac.ls_offset + lsa));
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_DMAC(LOG_ERROR, "Invalid register (SPU Thread Group MMIO)");
|
LOG_DMAC(LOG_ERROR, "Invalid register (SPU Thread Group MMIO)");
|
||||||
return false;
|
Emu.Pause();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_DMAC(LOG_ERROR, "Thread group not set (SPU Thread Group MMIO)");
|
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)
|
else if (ea >= RAW_SPU_BASE_ADDR && size == 4)
|
||||||
|
@ -632,19 +636,20 @@ public:
|
||||||
case MFC_PUT_CMD:
|
case MFC_PUT_CMD:
|
||||||
{
|
{
|
||||||
Memory.Write32(ea, ReadLS32(lsa));
|
Memory.Write32(ea, ReadLS32(lsa));
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case MFC_GET_CMD:
|
case MFC_GET_CMD:
|
||||||
{
|
{
|
||||||
WriteLS32(lsa, Memory.Read32(ea));
|
WriteLS32(lsa, Memory.Read32(ea));
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
LOG_DMAC(LOG_ERROR, "Unknown DMA command");
|
LOG_DMAC(LOG_ERROR, "Unknown DMA command");
|
||||||
return false;
|
Emu.Pause();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -653,53 +658,27 @@ public:
|
||||||
{
|
{
|
||||||
case MFC_PUT_CMD:
|
case MFC_PUT_CMD:
|
||||||
{
|
{
|
||||||
if (Memory.Copy(ea, dmac.ls_offset + lsa, size))
|
memcpy(Memory + ea, Memory + dmac.ls_offset + lsa, size);
|
||||||
{
|
return;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_DMAC(LOG_ERROR, "PUT* cmd failed");
|
|
||||||
return false; // TODO: page fault (?)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case MFC_GET_CMD:
|
case MFC_GET_CMD:
|
||||||
{
|
{
|
||||||
if (Memory.Copy(dmac.ls_offset + lsa, ea, size))
|
memcpy(Memory + dmac.ls_offset + lsa, Memory + ea, size);
|
||||||
{
|
return;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_DMAC(LOG_ERROR, "GET* cmd failed");
|
|
||||||
return false; // TODO: page fault (?)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
LOG_DMAC(LOG_ERROR, "Unknown DMA command");
|
LOG_DMAC(LOG_ERROR, "Unknown DMA command");
|
||||||
return false; // ???
|
Emu.Pause();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef LOG_CMD
|
#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)
|
void ListCmd(u32 lsa, u64 ea, u16 tag, u16 size, u32 cmd, MFCReg& MFCArgs)
|
||||||
{
|
{
|
||||||
u32 list_addr = ea & 0x3ffff;
|
u32 list_addr = ea & 0x3ffff;
|
||||||
|
@ -713,7 +692,7 @@ public:
|
||||||
be_t<u32> ea; // External Address Low
|
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++)
|
for (u32 i = 0; i < list_size; i++)
|
||||||
{
|
{
|
||||||
|
@ -723,15 +702,12 @@ public:
|
||||||
if (size < 16 && size != 1 && size != 2 && size != 4 && size != 8)
|
if (size < 16 && size != 1 && size != 2 && size != 4 && size != 8)
|
||||||
{
|
{
|
||||||
LOG_ERROR(Log::SPU, "DMA List: invalid transfer size(%d)", size);
|
LOG_ERROR(Log::SPU, "DMA List: invalid transfer size(%d)", size);
|
||||||
return;
|
result = MFC_PPU_DMA_CMD_SEQUENCE_ERROR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 addr = rec->ea;
|
u32 addr = rec->ea;
|
||||||
result = dmacCmd(cmd, tag, lsa | (addr & 0xf), addr, size);
|
ProcessCmd(cmd, tag, lsa | (addr & 0xf), addr, size);
|
||||||
if (result == MFC_PPU_DMA_CMD_SEQUENCE_ERROR)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Ini.HLELogging.GetValue() || rec->s)
|
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)",
|
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)
|
if (StallList[tag].MFCArgs)
|
||||||
{
|
{
|
||||||
LOG_ERROR(Log::SPU, "DMA List: existing stalled list found (tag=%d)", tag);
|
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].MFCArgs = &MFCArgs;
|
||||||
StallList[tag].cmd = cmd;
|
StallList[tag].cmd = cmd;
|
||||||
|
@ -753,7 +731,7 @@ public:
|
||||||
StallList[tag].lsa = lsa;
|
StallList[tag].lsa = lsa;
|
||||||
StallList[tag].size = (list_size - i - 1) * 8;
|
StallList[tag].size = (list_size - i - 1) * 8;
|
||||||
|
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -784,7 +762,8 @@ public:
|
||||||
(op & MFC_FENCE_MASK ? "F" : ""),
|
(op & MFC_FENCE_MASK ? "F" : ""),
|
||||||
lsa, ea, tag, size, cmd);
|
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;
|
break;
|
||||||
|
|
||||||
|
@ -871,21 +850,6 @@ public:
|
||||||
{
|
{
|
||||||
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE);
|
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
|
else
|
||||||
|
|
Loading…
Reference in New Issue