Skip to content

Commit

Permalink
Prefetch mfc list elemets to protect from overwriting
Browse files Browse the repository at this point in the history
  • Loading branch information
elad335 committed Jan 15, 2019
1 parent f19fd23 commit 1ee25c4
Showing 1 changed file with 37 additions and 18 deletions.
55 changes: 37 additions & 18 deletions rpcs3/Emu/Cell/SPUThread.cpp
Expand Up @@ -970,37 +970,39 @@ bool spu_thread::do_dma_check(const spu_mfc_cmd& args)

bool spu_thread::do_list_transfer(spu_mfc_cmd& args)
{
// Amount of elements to fetch in one go
static constexpr size_t fetch_size = 6;

struct list_element
{
be_t<u16> sb; // Stall-and-Notify bit (0x8000)
be_t<u16> ts; // List Transfer Size
be_t<u32> ea; // External Address Low
} item{};
} items[fetch_size];

u32 index = 0;

while (args.size)
{
if (UNLIKELY(item.sb & 0x8000))
// Check if fetching is needed
if (index % fetch_size == 0)
{
ch_stall_mask |= utils::rol32(1, args.tag);

if (!ch_stall_stat.get_count())
{
ch_event_stat |= SPU_EVENT_SN;
}

ch_stall_stat.set_value(utils::rol32(1, args.tag) | ch_stall_stat.get_value());

args.tag |= 0x80; // Set stalled status
return false;
auto src = _ptr<list_element>(args.eal & 0x3fff8);
items[0] = src[0];
items[1] = src[1];
items[2] = src[2];
items[3] = src[3];
items[4] = src[4];
items[5] = src[5];
index = 0;
}

args.lsa &= 0x3fff0;
item = _ref<list_element>(args.eal & 0x3fff8);
const u32 size = items[index].ts & 0x7fff;
const u32 addr = items[index].ea;

const u32 size = item.ts & 0x7fff;
const u32 addr = item.ea;
args.lsa &= 0x3fff0;

LOG_TRACE(SPU, "LIST: addr=0x%x, size=0x%x, lsa=0x%05x, sb=0x%x", addr, size, args.lsa | (addr & 0xf), item.sb);
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)
{
Expand All @@ -1019,6 +1021,23 @@ bool spu_thread::do_list_transfer(spu_mfc_cmd& args)

args.eal += 8;
args.size -= 8;

if (UNLIKELY(items[index].sb & 0x8000 && args.size))
{
ch_stall_mask |= utils::rol32(1, args.tag);

if (!ch_stall_stat.get_count())
{
ch_event_stat |= SPU_EVENT_SN;
}

ch_stall_stat.set_value(utils::rol32(1, args.tag) | ch_stall_stat.get_value());

args.tag |= 0x80; // Set stalled status
return false;
}

index++;
}

return true;
Expand Down

0 comments on commit 1ee25c4

Please sign in to comment.