Transactions: touch memory only after a failure

Minor optimization
This commit is contained in:
Nekotekina 2018-05-17 22:19:26 +03:00
parent 0b1c8bc676
commit 67391322f4
2 changed files with 20 additions and 37 deletions

View file

@ -999,13 +999,6 @@ const auto ppu_stwcx_tx = build_function_asm<int(*)(u32 raddr, u64 rtime, u64 rd
c.bswap(args[2].r32()); c.bswap(args[2].r32());
c.bswap(args[3].r32()); c.bswap(args[3].r32());
// Touch memory (heavyweight)
c.lock().add(x86::dword_ptr(x86::r11), 0);
c.xor_(x86::eax, x86::eax);
c.lock().xadd(x86::qword_ptr(x86::r10), x86::rax);
c.cmp(x86::rax, args[1]);
c.jne(fail);
// Begin transaction // Begin transaction
build_transaction_enter(c, fall); build_transaction_enter(c, fall);
c.cmp(x86::qword_ptr(x86::r10), args[1]); c.cmp(x86::qword_ptr(x86::r10), args[1]);
@ -1022,21 +1015,23 @@ const auto ppu_stwcx_tx = build_function_asm<int(*)(u32 raddr, u64 rtime, u64 rd
c.mov(x86::eax, 1); c.mov(x86::eax, 1);
c.ret(); c.ret();
// Touch memory after transaction failure
c.bind(fall); c.bind(fall);
c.lock().add(x86::dword_ptr(x86::r11), 0);
c.lock().add(x86::qword_ptr(x86::r10), 0);
c.sar(x86::eax, 24); c.sar(x86::eax, 24);
c.ret(); c.ret();
c.bind(fail); c.bind(fail);
build_transaction_abort(c, 0xff); build_transaction_abort(c, 0xff);
c.or_(x86::eax, -1); c.int3();
c.ret();
}); });
extern bool ppu_stwcx(ppu_thread& ppu, u32 addr, u32 reg_value) extern bool ppu_stwcx(ppu_thread& ppu, u32 addr, u32 reg_value)
{ {
atomic_be_t<u32>& data = vm::_ref<atomic_be_t<u32>>(addr); atomic_be_t<u32>& data = vm::_ref<atomic_be_t<u32>>(addr);
if (ppu.raddr != addr || ppu.rdata != data.load()) if (ppu.raddr != addr || ppu.rdata != data.load() || ppu.rtime != vm::reservation_acquire(addr, sizeof(u32)))
{ {
ppu.raddr = 0; ppu.raddr = 0;
return false; return false;
@ -1101,13 +1096,6 @@ const auto ppu_stdcx_tx = build_function_asm<int(*)(u32 raddr, u64 rtime, u64 rd
c.bswap(args[2]); c.bswap(args[2]);
c.bswap(args[3]); c.bswap(args[3]);
// Touch memory (heavyweight)
c.lock().add(x86::qword_ptr(x86::r11), 0);
c.xor_(x86::eax, x86::eax);
c.lock().xadd(x86::qword_ptr(x86::r10), x86::rax);
c.cmp(x86::rax, args[1]);
c.jne(fail);
// Begin transaction // Begin transaction
build_transaction_enter(c, fall); build_transaction_enter(c, fall);
c.cmp(x86::qword_ptr(x86::r10), args[1]); c.cmp(x86::qword_ptr(x86::r10), args[1]);
@ -1124,21 +1112,23 @@ const auto ppu_stdcx_tx = build_function_asm<int(*)(u32 raddr, u64 rtime, u64 rd
c.mov(x86::eax, 1); c.mov(x86::eax, 1);
c.ret(); c.ret();
// Touch memory after transaction failure
c.bind(fall); c.bind(fall);
c.lock().add(x86::qword_ptr(x86::r11), 0);
c.lock().add(x86::qword_ptr(x86::r10), 0);
c.sar(x86::eax, 24); c.sar(x86::eax, 24);
c.ret(); c.ret();
c.bind(fail); c.bind(fail);
build_transaction_abort(c, 0xff); build_transaction_abort(c, 0xff);
c.or_(x86::eax, -1); c.int3();
c.ret();
}); });
extern bool ppu_stdcx(ppu_thread& ppu, u32 addr, u64 reg_value) extern bool ppu_stdcx(ppu_thread& ppu, u32 addr, u64 reg_value)
{ {
atomic_be_t<u64>& data = vm::_ref<atomic_be_t<u64>>(addr); atomic_be_t<u64>& data = vm::_ref<atomic_be_t<u64>>(addr);
if (ppu.raddr != addr || ppu.rdata != data.load()) if (ppu.raddr != addr || ppu.rdata != data.load() || ppu.rtime != vm::reservation_acquire(addr, sizeof(u64)))
{ {
ppu.raddr = 0; ppu.raddr = 0;
return false; return false;

View file

@ -229,13 +229,6 @@ const auto spu_putllc_tx = build_function_asm<int(*)(u32 raddr, u64 rtime, const
c.shr(args[0], 4); c.shr(args[0], 4);
c.lea(x86::r10, x86::qword_ptr(x86::r10, args[0])); c.lea(x86::r10, x86::qword_ptr(x86::r10, args[0]));
// Touch memory (heavyweight)
c.lock().add(x86::qword_ptr(x86::r11), 0);
c.xor_(x86::eax, x86::eax);
c.lock().xadd(x86::qword_ptr(x86::r10), x86::rax);
c.cmp(x86::rax, args[1]);
c.jne(fail);
// Prepare data (Windows has only 6 volatile vector registers) // Prepare data (Windows has only 6 volatile vector registers)
c.vmovups(x86::ymm0, x86::yword_ptr(args[2], 0)); c.vmovups(x86::ymm0, x86::yword_ptr(args[2], 0));
c.vmovups(x86::ymm1, x86::yword_ptr(args[2], 32)); c.vmovups(x86::ymm1, x86::yword_ptr(args[2], 32));
@ -287,14 +280,16 @@ const auto spu_putllc_tx = build_function_asm<int(*)(u32 raddr, u64 rtime, const
c.mov(x86::eax, 1); c.mov(x86::eax, 1);
c.ret(); c.ret();
// Touch memory after transaction failure
c.bind(fall); c.bind(fall);
c.lock().add(x86::qword_ptr(x86::r11), 0);
c.lock().add(x86::qword_ptr(x86::r10), 0);
c.sar(x86::eax, 24); c.sar(x86::eax, 24);
c.ret(); c.ret();
c.bind(fail); c.bind(fail);
build_transaction_abort(c, 0xff); build_transaction_abort(c, 0xff);
c.or_(x86::eax, -1); c.int3();
c.ret();
}); });
const auto spu_getll_tx = build_function_asm<u64(*)(u32 raddr, void* rdata)>([](asmjit::X86Assembler& c, auto& args) const auto spu_getll_tx = build_function_asm<u64(*)(u32 raddr, void* rdata)>([](asmjit::X86Assembler& c, auto& args)
@ -312,10 +307,6 @@ const auto spu_getll_tx = build_function_asm<u64(*)(u32 raddr, void* rdata)>([](
c.shr(args[0], 4); c.shr(args[0], 4);
c.lea(x86::r10, x86::qword_ptr(x86::r10, args[0])); c.lea(x86::r10, x86::qword_ptr(x86::r10, args[0]));
// Touch memory
c.mov(x86::rax, x86::qword_ptr(x86::r11));
c.mov(x86::rax, x86::qword_ptr(x86::r10));
// Begin transaction // Begin transaction
build_transaction_enter(c, fall); build_transaction_enter(c, fall);
c.mov(x86::rax, x86::qword_ptr(x86::r10)); c.mov(x86::rax, x86::qword_ptr(x86::r10));
@ -331,7 +322,10 @@ const auto spu_getll_tx = build_function_asm<u64(*)(u32 raddr, void* rdata)>([](
c.vzeroupper(); c.vzeroupper();
c.ret(); c.ret();
// Touch memory after transaction failure
c.bind(fall); c.bind(fall);
c.mov(x86::rax, x86::qword_ptr(x86::r11));
c.mov(x86::rax, x86::qword_ptr(x86::r10));
c.mov(x86::eax, 1); c.mov(x86::eax, 1);
c.ret(); c.ret();
}); });
@ -351,10 +345,6 @@ const auto spu_putlluc_tx = build_function_asm<bool(*)(u32 raddr, const void* rd
c.shr(args[0], 4); c.shr(args[0], 4);
c.lea(x86::r10, x86::qword_ptr(x86::r10, args[0])); c.lea(x86::r10, x86::qword_ptr(x86::r10, args[0]));
// Touch memory (heavyweight)
c.lock().add(x86::qword_ptr(x86::r11), 0);
c.lock().add(x86::qword_ptr(x86::r10), 0);
// Prepare data // Prepare data
c.vmovups(x86::ymm0, x86::yword_ptr(args[1], 0)); c.vmovups(x86::ymm0, x86::yword_ptr(args[1], 0));
c.vmovups(x86::ymm1, x86::yword_ptr(args[1], 32)); c.vmovups(x86::ymm1, x86::yword_ptr(args[1], 32));
@ -377,7 +367,10 @@ const auto spu_putlluc_tx = build_function_asm<bool(*)(u32 raddr, const void* rd
c.mov(x86::eax, 1); c.mov(x86::eax, 1);
c.ret(); c.ret();
// Touch memory after transaction failure
c.bind(fall); c.bind(fall);
c.lock().add(x86::qword_ptr(x86::r11), 0);
c.lock().add(x86::qword_ptr(x86::r10), 0);
c.xor_(x86::eax, x86::eax); c.xor_(x86::eax, x86::eax);
c.ret(); c.ret();
}); });