ldarx/lwarx/stdcx/stwcx. Probably.
This commit is contained in:
parent
f2550bd017
commit
0746e6feb2
|
@ -1000,8 +1000,6 @@ XEEMITTER(ldarx, 0x7C0000A8, X )(X64Emitter& e, X86Compiler& c, InstrDat
|
|||
// RESERVE_ADDR <- real_addr(EA)
|
||||
// RT <- MEM(EA, 8)
|
||||
|
||||
// TODO(benvanik): make this right
|
||||
|
||||
GpVar ea(c.newGpVar());
|
||||
c.mov(ea, e.gpr_value(i.X.RB));
|
||||
if (i.X.RA) {
|
||||
|
@ -1026,8 +1024,6 @@ XEEMITTER(lwarx, 0x7C000028, X )(X64Emitter& e, X86Compiler& c, InstrDat
|
|||
// RESERVE_ADDR <- real_addr(EA)
|
||||
// RT <- i32.0 || MEM(EA, 4)
|
||||
|
||||
// TODO(benvanik): make this right
|
||||
|
||||
GpVar ea(c.newGpVar());
|
||||
c.mov(ea, e.gpr_value(i.X.RB));
|
||||
if (i.X.RA) {
|
||||
|
@ -1052,8 +1048,6 @@ XEEMITTER(stdcx, 0x7C0001AD, X )(X64Emitter& e, X86Compiler& c, InstrDat
|
|||
// n <- 1 if store performed
|
||||
// CR0[LT GT EQ SO] = 0b00 || n || XER[SO]
|
||||
|
||||
// TODO(benvanik): make this right
|
||||
|
||||
GpVar ea(c.newGpVar());
|
||||
c.mov(ea, e.gpr_value(i.X.RB));
|
||||
if (i.X.RA) {
|
||||
|
@ -1062,9 +1056,6 @@ XEEMITTER(stdcx, 0x7C0001AD, X )(X64Emitter& e, X86Compiler& c, InstrDat
|
|||
GpVar v = e.gpr_value(i.X.RT);
|
||||
e.WriteMemory(i.address, ea, 8, v, /* release */ true);
|
||||
|
||||
// We always succeed.
|
||||
e.update_cr_value(0, e.get_uint64(1 << 2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1079,8 +1070,6 @@ XEEMITTER(stwcx, 0x7C00012D, X )(X64Emitter& e, X86Compiler& c, InstrDat
|
|||
// n <- 1 if store performed
|
||||
// CR0[LT GT EQ SO] = 0b00 || n || XER[SO]
|
||||
|
||||
// TODO(benvanik): make this right
|
||||
|
||||
GpVar ea(c.newGpVar());
|
||||
c.mov(ea, e.gpr_value(i.X.RB));
|
||||
if (i.X.RA) {
|
||||
|
@ -1089,9 +1078,6 @@ XEEMITTER(stwcx, 0x7C00012D, X )(X64Emitter& e, X86Compiler& c, InstrDat
|
|||
GpVar v = e.gpr_value(i.X.RT);
|
||||
e.WriteMemory(i.address, ea, 4, v, /* release */ true);
|
||||
|
||||
// We always succeed.
|
||||
e.update_cr_value(0, e.get_uint64(1 << 2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1852,6 +1852,8 @@ GpVar X64Emitter::TouchMemoryAddress(uint32_t cia, GpVar& addr) {
|
|||
return real_address;
|
||||
}
|
||||
|
||||
uint64_t X64Emitter::reserved_addr_ = 0;
|
||||
|
||||
GpVar X64Emitter::ReadMemory(
|
||||
uint32_t cia, GpVar& addr, uint32_t size, bool acquire) {
|
||||
X86Compiler& c = compiler_;
|
||||
|
@ -1859,12 +1861,15 @@ GpVar X64Emitter::ReadMemory(
|
|||
// Rebase off of memory base pointer.
|
||||
GpVar real_address = TouchMemoryAddress(cia, addr);
|
||||
|
||||
// Acquire semantics -- make reservation for address.
|
||||
// Note that we overwrite any other reservation.
|
||||
if (acquire) {
|
||||
// TODO(benvanik): acquire semantics.
|
||||
// load_value->setAlignment(size);
|
||||
// load_value->setVolatile(true);
|
||||
// load_value->setAtomic(Acquire);
|
||||
XELOGE("Ignoring acquire semantics on read -- TODO");
|
||||
GpVar reservation(c.newGpVar());
|
||||
c.mov(reservation, real_address);
|
||||
GpVar reserved_addr(c.newGpVar());
|
||||
c.mov(reserved_addr, imm((sysint_t)&X64Emitter::reserved_addr_));
|
||||
c.lock();
|
||||
c.xchg(reservation, qword_ptr(reserved_addr));
|
||||
}
|
||||
|
||||
GpVar value(c.newGpVar());
|
||||
|
@ -1904,6 +1909,31 @@ void X64Emitter::WriteMemory(
|
|||
// Rebase off of memory base pointer.
|
||||
GpVar real_address = TouchMemoryAddress(cia, addr);
|
||||
|
||||
// Release semantics - clear reservation.
|
||||
Label reservation_mismatch(c.newLabel());
|
||||
if (release) {
|
||||
// Atomically swap 0 with the reserved_addr_ -- this clears the reservation
|
||||
// and lets us compare -- if we match, we can write.
|
||||
GpVar reservation(c.newGpVar());
|
||||
c.alloc(reservation, rax);
|
||||
c.xor_(reservation, reservation);
|
||||
GpVar reserved_addr(c.newGpVar());
|
||||
c.mov(reserved_addr, imm((sysint_t)&X64Emitter::reserved_addr_));
|
||||
c.lock();
|
||||
c.xchg(reservation, qword_ptr(reserved_addr));
|
||||
// If reservation was not for address, skip write.
|
||||
GpVar cr(c.newGpVar());
|
||||
c.xor_(cr, cr);
|
||||
GpVar cr_set(c.newGpVar());
|
||||
c.mov(cr_set, imm(1 << 2));
|
||||
c.cmp(reservation, real_address);
|
||||
c.unuse(reservation);
|
||||
c.cmove(cr, cr_set);
|
||||
update_cr_value(0, cr);
|
||||
c.test(cr, cr);
|
||||
c.jz(reservation_mismatch, kCondHintUnlikely);
|
||||
}
|
||||
|
||||
GpVar tmp;
|
||||
switch (size) {
|
||||
case 1:
|
||||
|
@ -1932,12 +1962,8 @@ void X64Emitter::WriteMemory(
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO(benvanik): release semantics
|
||||
if (release) {
|
||||
// store_value->setAlignment(size);
|
||||
// store_value->setVolatile(true);
|
||||
// store_value->setAtomic(Release);
|
||||
XELOGE("Ignoring release semantics on write -- TODO");
|
||||
c.bind(reservation_mismatch);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -142,6 +142,8 @@ private:
|
|||
void* gpu_read_;
|
||||
void* gpu_write_;
|
||||
|
||||
static uint64_t reserved_addr_;
|
||||
|
||||
AsmJit::Logger* logger_;
|
||||
AsmJit::X86Assembler assembler_;
|
||||
AsmJit::X86Compiler compiler_;
|
||||
|
|
Loading…
Reference in New Issue