1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-26 04:32:35 +01:00

SPU: cache barrier/fence masks

This commit is contained in:
Nekotekina 2018-04-03 16:09:43 +03:00
parent 90e0bade77
commit e88508b679
2 changed files with 54 additions and 21 deletions

View File

@ -349,6 +349,8 @@ void SPUThread::cpu_init()
srr0 = 0; srr0 = 0;
mfc_size = 0; mfc_size = 0;
mfc_barrier = -1;
mfc_fence = -1;
ch_tag_upd = 0; ch_tag_upd = 0;
ch_tag_mask = 0; ch_tag_mask = 0;
mfc_prxy_mask = 0; mfc_prxy_mask = 0;
@ -722,20 +724,49 @@ void SPUThread::do_dma_transfer(const spu_mfc_cmd& args)
bool SPUThread::do_dma_check(const spu_mfc_cmd& args) bool SPUThread::do_dma_check(const spu_mfc_cmd& args)
{ {
for (u32 i = 0; i < mfc_size; i++) const u32 mask = 1u << args.tag;
{
if (mfc_queue[i].cmd == MFC_BARRIER_CMD)
{
return false;
}
if (mfc_queue[i].tag == args.tag && mfc_queue[i].cmd != MFC_EIEIO_CMD) if (UNLIKELY(mfc_barrier & mask || (args.cmd & MFC_FENCE_MASK && mfc_fence & mask)))
{
// Check for special value combination (normally impossible)
if (UNLIKELY(mfc_barrier == -1 && mfc_fence == -1))
{ {
if (args.cmd & MFC_FENCE_MASK || mfc_queue[i].cmd & MFC_BARRIER_MASK) // Update barrier/fence masks if necessary
mfc_barrier = 0;
mfc_fence = 0;
for (u32 i = 0; i < mfc_size; i++)
{
if (mfc_queue[i].cmd == MFC_BARRIER_CMD)
{
mfc_barrier |= -1;
continue;
}
if (mfc_queue[i].cmd != MFC_EIEIO_CMD)
{
const u32 _mask = 1u << mfc_queue[i].tag;
// A command with barrier hard blocks that tag until it's been dealt with
if (mfc_queue[i].cmd & MFC_BARRIER_MASK)
{
mfc_barrier |= _mask;
}
// A new command that has a fence can't be executed until the stalled list has been dealt with
mfc_fence |= _mask;
}
}
if (mfc_barrier & mask || (args.cmd & MFC_FENCE_MASK && mfc_fence & mask))
{ {
return false; return false;
} }
return true;
} }
return false;
} }
return true; return true;
@ -845,6 +876,11 @@ void SPUThread::do_mfc()
u32 barrier = 0; u32 barrier = 0;
u32 fence = 0; u32 fence = 0;
// Check special value
if (UNLIKELY(mfc_barrier == -1 && mfc_fence == -1))
{
}
// Process enqueued commands // Process enqueued commands
std::remove_if(mfc_queue + 0, mfc_queue + mfc_size, [&](spu_mfc_cmd& args) std::remove_if(mfc_queue + 0, mfc_queue + mfc_size, [&](spu_mfc_cmd& args)
{ {
@ -861,7 +897,7 @@ void SPUThread::do_mfc()
if (args.cmd == MFC_BARRIER_CMD) if (args.cmd == MFC_BARRIER_CMD)
{ {
// Block all tags // Block all tags
barrier |= 0xffffffffu; barrier |= -1;
} }
return false; return false;
@ -870,15 +906,9 @@ void SPUThread::do_mfc()
// Select tag bit in the tag mask or the stall mask // Select tag bit in the tag mask or the stall mask
const u32 mask = 1u << args.tag; const u32 mask = 1u << args.tag;
// A list with barrier hard blocks that tag until it's been dealt with
if (barrier & mask) if (barrier & mask)
{ {
return false; fence |= mask;
}
// A new command that has a fence can't be executed until the stalled list has been dealt with
if (args.cmd & MFC_FENCE_MASK && fence & mask)
{
return false; return false;
} }
@ -890,8 +920,6 @@ void SPUThread::do_mfc()
return true; return true;
} }
fence |= mask;
if (args.cmd & MFC_BARRIER_MASK) if (args.cmd & MFC_BARRIER_MASK)
{ {
barrier |= mask; barrier |= mask;
@ -899,9 +927,10 @@ void SPUThread::do_mfc()
if (test(state, cpu_flag::stop)) if (test(state, cpu_flag::stop))
{ {
barrier |= 0xffffffffu; barrier |= -1;
} }
fence |= mask;
return false; return false;
} }
@ -913,7 +942,7 @@ void SPUThread::do_mfc()
return true; return true;
} }
barrier |= 0xffffffffu; barrier |= -1;
return false; return false;
} }
@ -930,7 +959,7 @@ void SPUThread::do_mfc()
args.cmd & MFC_PUT_CMD ? "writing" : "reading", args.cmd & MFC_PUT_CMD ? "writing" : "reading",
args.eal, args.cmd, args.size); args.eal, args.cmd, args.size);
barrier |= 0xffffffffu; barrier |= -1;
return false; return false;
} }
@ -942,6 +971,8 @@ void SPUThread::do_mfc()
}); });
mfc_size -= removed; mfc_size -= removed;
mfc_barrier = barrier;
mfc_fence = fence;
if (removed && ch_tag_upd) if (removed && ch_tag_upd)
{ {

View File

@ -532,6 +532,8 @@ public:
// MFC command queue // MFC command queue
spu_mfc_cmd mfc_queue[16]{}; spu_mfc_cmd mfc_queue[16]{};
u32 mfc_size = 0; u32 mfc_size = 0;
u32 mfc_barrier = -1;
u32 mfc_fence = -1;
atomic_t<u32> mfc_prxy_mask; atomic_t<u32> mfc_prxy_mask;
// Reservation Data // Reservation Data