mirror of
https://github.com/xenia-project/xenia.git
synced 2025-12-06 07:12:03 +01:00
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)
|
// RESERVE_ADDR <- real_addr(EA)
|
||||||
// RT <- MEM(EA, 8)
|
// RT <- MEM(EA, 8)
|
||||||
|
|
||||||
// TODO(benvanik): make this right
|
|
||||||
|
|
||||||
GpVar ea(c.newGpVar());
|
GpVar ea(c.newGpVar());
|
||||||
c.mov(ea, e.gpr_value(i.X.RB));
|
c.mov(ea, e.gpr_value(i.X.RB));
|
||||||
if (i.X.RA) {
|
if (i.X.RA) {
|
||||||
|
|
@ -1026,8 +1024,6 @@ XEEMITTER(lwarx, 0x7C000028, X )(X64Emitter& e, X86Compiler& c, InstrDat
|
||||||
// RESERVE_ADDR <- real_addr(EA)
|
// RESERVE_ADDR <- real_addr(EA)
|
||||||
// RT <- i32.0 || MEM(EA, 4)
|
// RT <- i32.0 || MEM(EA, 4)
|
||||||
|
|
||||||
// TODO(benvanik): make this right
|
|
||||||
|
|
||||||
GpVar ea(c.newGpVar());
|
GpVar ea(c.newGpVar());
|
||||||
c.mov(ea, e.gpr_value(i.X.RB));
|
c.mov(ea, e.gpr_value(i.X.RB));
|
||||||
if (i.X.RA) {
|
if (i.X.RA) {
|
||||||
|
|
@ -1052,8 +1048,6 @@ XEEMITTER(stdcx, 0x7C0001AD, X )(X64Emitter& e, X86Compiler& c, InstrDat
|
||||||
// n <- 1 if store performed
|
// n <- 1 if store performed
|
||||||
// CR0[LT GT EQ SO] = 0b00 || n || XER[SO]
|
// CR0[LT GT EQ SO] = 0b00 || n || XER[SO]
|
||||||
|
|
||||||
// TODO(benvanik): make this right
|
|
||||||
|
|
||||||
GpVar ea(c.newGpVar());
|
GpVar ea(c.newGpVar());
|
||||||
c.mov(ea, e.gpr_value(i.X.RB));
|
c.mov(ea, e.gpr_value(i.X.RB));
|
||||||
if (i.X.RA) {
|
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);
|
GpVar v = e.gpr_value(i.X.RT);
|
||||||
e.WriteMemory(i.address, ea, 8, v, /* release */ true);
|
e.WriteMemory(i.address, ea, 8, v, /* release */ true);
|
||||||
|
|
||||||
// We always succeed.
|
|
||||||
e.update_cr_value(0, e.get_uint64(1 << 2));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1079,8 +1070,6 @@ XEEMITTER(stwcx, 0x7C00012D, X )(X64Emitter& e, X86Compiler& c, InstrDat
|
||||||
// n <- 1 if store performed
|
// n <- 1 if store performed
|
||||||
// CR0[LT GT EQ SO] = 0b00 || n || XER[SO]
|
// CR0[LT GT EQ SO] = 0b00 || n || XER[SO]
|
||||||
|
|
||||||
// TODO(benvanik): make this right
|
|
||||||
|
|
||||||
GpVar ea(c.newGpVar());
|
GpVar ea(c.newGpVar());
|
||||||
c.mov(ea, e.gpr_value(i.X.RB));
|
c.mov(ea, e.gpr_value(i.X.RB));
|
||||||
if (i.X.RA) {
|
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);
|
GpVar v = e.gpr_value(i.X.RT);
|
||||||
e.WriteMemory(i.address, ea, 4, v, /* release */ true);
|
e.WriteMemory(i.address, ea, 4, v, /* release */ true);
|
||||||
|
|
||||||
// We always succeed.
|
|
||||||
e.update_cr_value(0, e.get_uint64(1 << 2));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1852,6 +1852,8 @@ GpVar X64Emitter::TouchMemoryAddress(uint32_t cia, GpVar& addr) {
|
||||||
return real_address;
|
return real_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t X64Emitter::reserved_addr_ = 0;
|
||||||
|
|
||||||
GpVar X64Emitter::ReadMemory(
|
GpVar X64Emitter::ReadMemory(
|
||||||
uint32_t cia, GpVar& addr, uint32_t size, bool acquire) {
|
uint32_t cia, GpVar& addr, uint32_t size, bool acquire) {
|
||||||
X86Compiler& c = compiler_;
|
X86Compiler& c = compiler_;
|
||||||
|
|
@ -1859,12 +1861,15 @@ GpVar X64Emitter::ReadMemory(
|
||||||
// Rebase off of memory base pointer.
|
// Rebase off of memory base pointer.
|
||||||
GpVar real_address = TouchMemoryAddress(cia, addr);
|
GpVar real_address = TouchMemoryAddress(cia, addr);
|
||||||
|
|
||||||
|
// Acquire semantics -- make reservation for address.
|
||||||
|
// Note that we overwrite any other reservation.
|
||||||
if (acquire) {
|
if (acquire) {
|
||||||
// TODO(benvanik): acquire semantics.
|
GpVar reservation(c.newGpVar());
|
||||||
// load_value->setAlignment(size);
|
c.mov(reservation, real_address);
|
||||||
// load_value->setVolatile(true);
|
GpVar reserved_addr(c.newGpVar());
|
||||||
// load_value->setAtomic(Acquire);
|
c.mov(reserved_addr, imm((sysint_t)&X64Emitter::reserved_addr_));
|
||||||
XELOGE("Ignoring acquire semantics on read -- TODO");
|
c.lock();
|
||||||
|
c.xchg(reservation, qword_ptr(reserved_addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
GpVar value(c.newGpVar());
|
GpVar value(c.newGpVar());
|
||||||
|
|
@ -1904,6 +1909,31 @@ void X64Emitter::WriteMemory(
|
||||||
// Rebase off of memory base pointer.
|
// Rebase off of memory base pointer.
|
||||||
GpVar real_address = TouchMemoryAddress(cia, addr);
|
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;
|
GpVar tmp;
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 1:
|
case 1:
|
||||||
|
|
@ -1932,12 +1962,8 @@ void X64Emitter::WriteMemory(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(benvanik): release semantics
|
|
||||||
if (release) {
|
if (release) {
|
||||||
// store_value->setAlignment(size);
|
c.bind(reservation_mismatch);
|
||||||
// store_value->setVolatile(true);
|
|
||||||
// store_value->setAtomic(Release);
|
|
||||||
XELOGE("Ignoring release semantics on write -- TODO");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,8 @@ private:
|
||||||
void* gpu_read_;
|
void* gpu_read_;
|
||||||
void* gpu_write_;
|
void* gpu_write_;
|
||||||
|
|
||||||
|
static uint64_t reserved_addr_;
|
||||||
|
|
||||||
AsmJit::Logger* logger_;
|
AsmJit::Logger* logger_;
|
||||||
AsmJit::X86Assembler assembler_;
|
AsmJit::X86Assembler assembler_;
|
||||||
AsmJit::X86Compiler compiler_;
|
AsmJit::X86Compiler compiler_;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue