mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-07 07:21:25 +12:00
Prefetch MFC list elements (#5345)
* Prefetch mfc list elemets to protect from overwriting Also move some stuff away from command processing such as a few constant arguments setup
This commit is contained in:
parent
85b1152e29
commit
49aefc0795
1 changed files with 67 additions and 30 deletions
|
@ -1500,16 +1500,77 @@ bool spu_thread::do_dma_check(const spu_mfc_cmd& args)
|
||||||
|
|
||||||
bool spu_thread::do_list_transfer(spu_mfc_cmd& args)
|
bool spu_thread::do_list_transfer(spu_mfc_cmd& args)
|
||||||
{
|
{
|
||||||
struct list_element
|
// Amount of elements to fetch in one go
|
||||||
|
constexpr u32 fetch_size = 6;
|
||||||
|
|
||||||
|
struct alignas(8) list_element
|
||||||
{
|
{
|
||||||
be_t<u16> sb; // Stall-and-Notify bit (0x8000)
|
be_t<u16> sb; // Stall-and-Notify bit (0x8000)
|
||||||
be_t<u16> ts; // List Transfer Size
|
be_t<u16> ts; // List Transfer Size
|
||||||
be_t<u32> ea; // External Address Low
|
be_t<u32> ea; // External Address Low
|
||||||
} item{};
|
};
|
||||||
|
|
||||||
while (args.size)
|
union
|
||||||
{
|
{
|
||||||
if (UNLIKELY(item.sb & 0x8000))
|
list_element items[fetch_size];
|
||||||
|
alignas(v128) char bufitems[sizeof(items)];
|
||||||
|
};
|
||||||
|
|
||||||
|
spu_mfc_cmd transfer;
|
||||||
|
transfer.eah = 0;
|
||||||
|
transfer.tag = args.tag;
|
||||||
|
transfer.cmd = MFC(args.cmd & ~MFC_LIST_MASK);
|
||||||
|
|
||||||
|
args.lsa &= 0x3fff0;
|
||||||
|
|
||||||
|
u32 index = fetch_size;
|
||||||
|
|
||||||
|
// Assume called with size greater than 0
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// Check if fetching is needed
|
||||||
|
if (index == fetch_size)
|
||||||
|
{
|
||||||
|
// Reset to elements array head
|
||||||
|
index = 0;
|
||||||
|
|
||||||
|
const auto src = _ptr<const __m128i>(args.eal & 0x3fff8);
|
||||||
|
const v128 data0 = v128::fromV(_mm_loadu_si128(src + 0));
|
||||||
|
const v128 data1 = v128::fromV(_mm_loadu_si128(src + 1));
|
||||||
|
const v128 data2 = v128::fromV(_mm_loadu_si128(src + 2));
|
||||||
|
|
||||||
|
((v128*)+bufitems)[0] = data0;
|
||||||
|
((v128*)+bufitems)[1] = data1;
|
||||||
|
((v128*)+bufitems)[2] = data2;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 size = items[index].ts & 0x7fff;
|
||||||
|
const u32 addr = items[index].ea;
|
||||||
|
|
||||||
|
LOG_TRACE(SPU, "LIST: addr=0x%x, size=0x%x, lsa=0x%05x, sb=0x%x", addr, size, args.lsa | (addr & 0xf), items[index].sb);
|
||||||
|
|
||||||
|
if (size)
|
||||||
|
{
|
||||||
|
transfer.eal = addr;
|
||||||
|
transfer.lsa = args.lsa | (addr & 0xf);
|
||||||
|
transfer.size = size;
|
||||||
|
|
||||||
|
do_dma_transfer(transfer);
|
||||||
|
const u32 add_size = std::max<u32>(size, 16);
|
||||||
|
args.lsa += add_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
args.size -= 8;
|
||||||
|
|
||||||
|
if (!args.size)
|
||||||
|
{
|
||||||
|
// No more elements
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
args.eal += 8;
|
||||||
|
|
||||||
|
if (UNLIKELY(items[index].sb & 0x8000))
|
||||||
{
|
{
|
||||||
ch_stall_mask |= utils::rol32(1, args.tag);
|
ch_stall_mask |= utils::rol32(1, args.tag);
|
||||||
|
|
||||||
|
@ -1524,31 +1585,7 @@ bool spu_thread::do_list_transfer(spu_mfc_cmd& args)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
args.lsa &= 0x3fff0;
|
index++;
|
||||||
item = _ref<list_element>(args.eal & 0x3fff8);
|
|
||||||
|
|
||||||
const u32 size = item.ts & 0x7fff;
|
|
||||||
const u32 addr = item.ea;
|
|
||||||
|
|
||||||
LOG_TRACE(SPU, "LIST: addr=0x%x, size=0x%x, lsa=0x%05x, sb=0x%x", addr, size, args.lsa | (addr & 0xf), item.sb);
|
|
||||||
|
|
||||||
if (size)
|
|
||||||
{
|
|
||||||
spu_mfc_cmd transfer;
|
|
||||||
transfer.eal = addr;
|
|
||||||
transfer.eah = 0;
|
|
||||||
transfer.lsa = args.lsa | (addr & 0xf);
|
|
||||||
transfer.tag = args.tag;
|
|
||||||
transfer.cmd = MFC(args.cmd & ~MFC_LIST_MASK);
|
|
||||||
transfer.size = size;
|
|
||||||
|
|
||||||
do_dma_transfer(transfer);
|
|
||||||
const u32 add_size = std::max<u32>(size, 16);
|
|
||||||
args.lsa += add_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
args.eal += 8;
|
|
||||||
args.size -= 8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -2040,7 +2077,7 @@ bool spu_thread::process_mfc_cmd()
|
||||||
|
|
||||||
if (LIKELY(do_dma_check(cmd)))
|
if (LIKELY(do_dma_check(cmd)))
|
||||||
{
|
{
|
||||||
if (LIKELY(do_list_transfer(cmd)))
|
if (LIKELY(!cmd.size || do_list_transfer(cmd)))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue