Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PPU: Merge reservations store functions into one #8023

Merged
merged 1 commit into from Apr 13, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
105 changes: 25 additions & 80 deletions rpcs3/Emu/Cell/PPUThread.cpp
Expand Up @@ -1081,7 +1081,7 @@ extern u64 ppu_ldarx(ppu_thread& ppu, u32 addr)
return ppu_load_acquire_reservation<u64>(ppu, addr);
}

const auto ppu_stwcx_tx = build_function_asm<u32(*)(u32 raddr, u64 rtime, u64 rdata, u32 value)>([](asmjit::X86Assembler& c, auto& args)
const auto ppu_stwcx_tx = build_function_asm<u32(*)(u32 raddr, u64 rtime, u64 rdata, u64 value)>([](asmjit::X86Assembler& c, auto& args)
{
using namespace asmjit;

Expand Down Expand Up @@ -1127,76 +1127,6 @@ const auto ppu_stwcx_tx = build_function_asm<u32(*)(u32 raddr, u64 rtime, u64 rd
c.ret();
});

extern bool ppu_stwcx(ppu_thread& ppu, u32 addr, u32 reg_value)
{
auto& data = vm::_ref<atomic_be_t<u32>>(addr & -4);
const u32 old_data = static_cast<u32>(ppu.rdata << ((addr & 7) * 8) >> 32);

if (ppu.raddr != addr || addr & 3 || old_data != data.load() || ppu.rtime != (vm::reservation_acquire(addr, sizeof(u32)) & -128))
{
ppu.raddr = 0;
return false;
}

if (g_use_rtm) [[likely]]
{
switch (ppu_stwcx_tx(addr, ppu.rtime, old_data, reg_value))
{
case 0:
{
// Reservation lost
ppu.raddr = 0;
return false;
}
case 1:
{
vm::reservation_notifier(addr, sizeof(u32)).notify_all();
ppu.raddr = 0;
return true;
}
}

auto& res = vm::reservation_acquire(addr, sizeof(u32));

ppu.raddr = 0;

if (res == ppu.rtime && res.compare_and_swap_test(ppu.rtime, ppu.rtime | 1))
{
if (data.compare_and_swap_test(old_data, reg_value))
{
res += 127;
vm::reservation_notifier(addr, sizeof(u32)).notify_all();
return true;
}

res -= 1;
}

return false;
}

vm::passive_unlock(ppu);

auto& res = vm::reservation_lock(addr, sizeof(u32));
const u64 old_time = res.load() & -128;

const bool result = ppu.rtime == old_time && data.compare_and_swap_test(old_data, reg_value);

if (result)
{
res.release(old_time + 128);
vm::reservation_notifier(addr, sizeof(u32)).notify_all();
}
else
{
res.release(old_time);
}

vm::passive_lock(ppu);
ppu.raddr = 0;
return result;
}

const auto ppu_stdcx_tx = build_function_asm<u32(*)(u32 raddr, u64 rtime, u64 rdata, u64 value)>([](asmjit::X86Assembler& c, auto& args)
{
using namespace asmjit;
Expand Down Expand Up @@ -1243,20 +1173,25 @@ const auto ppu_stdcx_tx = build_function_asm<u32(*)(u32 raddr, u64 rtime, u64 rd
c.ret();
});

extern bool ppu_stdcx(ppu_thread& ppu, u32 addr, u64 reg_value)
template <typename T>
static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, T reg_value)
{
auto& data = vm::_ref<atomic_be_t<u64>>(addr & -8);
const u64 old_data = ppu.rdata << ((addr & 7) * 8);
auto& data = vm::_ref<atomic_be_t<T>>(addr & (0 - sizeof(T)));
constexpr u64 size_off = (sizeof(T) * 8) & 63;

const T old_data = static_cast<T>(ppu.rdata << ((addr & 7) * 8) >> size_off);

if (ppu.raddr != addr || addr & 7 || old_data != data.load() || ppu.rtime != (vm::reservation_acquire(addr, sizeof(u64)) & -128))
if (ppu.raddr != addr || addr % sizeof(T) || old_data != data.load() || ppu.rtime != (vm::reservation_acquire(addr, sizeof(T)) & -128))
{
ppu.raddr = 0;
return false;
}

if (g_use_rtm) [[likely]]
{
switch (ppu_stdcx_tx(addr, ppu.rtime, old_data, reg_value))
constexpr auto& ppu_store_tx = sizeof(T) == 8 ? ppu_stdcx_tx : ppu_stwcx_tx;

switch (ppu_store_tx(addr, ppu.rtime, old_data, reg_value))
{
case 0:
{
Expand All @@ -1266,13 +1201,13 @@ extern bool ppu_stdcx(ppu_thread& ppu, u32 addr, u64 reg_value)
}
case 1:
{
vm::reservation_notifier(addr, sizeof(u64)).notify_all();
vm::reservation_notifier(addr, sizeof(T)).notify_all();
ppu.raddr = 0;
return true;
}
}

auto& res = vm::reservation_acquire(addr, sizeof(u64));
auto& res = vm::reservation_acquire(addr, sizeof(T));

ppu.raddr = 0;

Expand All @@ -1281,7 +1216,7 @@ extern bool ppu_stdcx(ppu_thread& ppu, u32 addr, u64 reg_value)
if (data.compare_and_swap_test(old_data, reg_value))
{
res += 127;
vm::reservation_notifier(addr, sizeof(u64)).notify_all();
vm::reservation_notifier(addr, sizeof(T)).notify_all();
return true;
}

Expand All @@ -1293,7 +1228,7 @@ extern bool ppu_stdcx(ppu_thread& ppu, u32 addr, u64 reg_value)

vm::passive_unlock(ppu);

auto& res = vm::reservation_lock(addr, sizeof(u64));
auto& res = vm::reservation_lock(addr, sizeof(T));
const u64 old_time = res.load() & -128;

const bool result = ppu.rtime == old_time && data.compare_and_swap_test(old_data, reg_value);
Expand All @@ -1313,6 +1248,16 @@ extern bool ppu_stdcx(ppu_thread& ppu, u32 addr, u64 reg_value)
return result;
}

extern bool ppu_stwcx(ppu_thread& ppu, u32 addr, u32 reg_value)
{
return ppu_store_reservation<u32>(ppu, addr, reg_value);
}

extern bool ppu_stdcx(ppu_thread& ppu, u32 addr, u64 reg_value)
{
return ppu_store_reservation<u64>(ppu, addr, reg_value);
}

extern void ppu_initialize()
{
const auto _main = g_fxo->get<ppu_module>();
Expand Down