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:
parent
90e0bade77
commit
e88508b679
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user