emit_x64_memory: Share Emit{Read,Write}MemoryMove
This commit is contained in:
parent
64adc91ca2
commit
cf0709c7f1
3 changed files with 53 additions and 101 deletions
|
@ -158,50 +158,6 @@ FakeCall A32EmitX64::FastmemCallback(u64 rip_) {
|
|||
};
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
template<std::size_t bitsize>
|
||||
void EmitReadMemoryMov(BlockOfCode& code, const Xbyak::Reg64& value, const Xbyak::RegExp& addr) {
|
||||
switch (bitsize) {
|
||||
case 8:
|
||||
code.movzx(value.cvt32(), code.byte[addr]);
|
||||
return;
|
||||
case 16:
|
||||
code.movzx(value.cvt32(), word[addr]);
|
||||
return;
|
||||
case 32:
|
||||
code.mov(value.cvt32(), dword[addr]);
|
||||
return;
|
||||
case 64:
|
||||
code.mov(value, qword[addr]);
|
||||
return;
|
||||
default:
|
||||
ASSERT_FALSE("Invalid bitsize");
|
||||
}
|
||||
}
|
||||
|
||||
template<std::size_t bitsize>
|
||||
void EmitWriteMemoryMov(BlockOfCode& code, const Xbyak::RegExp& addr, const Xbyak::Reg64& value) {
|
||||
switch (bitsize) {
|
||||
case 8:
|
||||
code.mov(code.byte[addr], value.cvt8());
|
||||
return;
|
||||
case 16:
|
||||
code.mov(word[addr], value.cvt16());
|
||||
return;
|
||||
case 32:
|
||||
code.mov(dword[addr], value.cvt32());
|
||||
return;
|
||||
case 64:
|
||||
code.mov(qword[addr], value);
|
||||
return;
|
||||
default:
|
||||
ASSERT_FALSE("Invalid bitsize");
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
template<std::size_t bitsize, auto callback>
|
||||
void A32EmitX64::EmitMemoryRead(A32EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
@ -225,7 +181,7 @@ void A32EmitX64::EmitMemoryRead(A32EmitContext& ctx, IR::Inst* inst) {
|
|||
const auto src_ptr = r13 + vaddr;
|
||||
|
||||
const auto location = code.getCurr();
|
||||
EmitReadMemoryMov<bitsize>(code, value, src_ptr);
|
||||
EmitReadMemoryMov<bitsize>(code, value.getIdx(), src_ptr);
|
||||
|
||||
fastmem_patch_info.emplace(
|
||||
Common::BitCast<u64>(location),
|
||||
|
@ -245,7 +201,7 @@ void A32EmitX64::EmitMemoryRead(A32EmitContext& ctx, IR::Inst* inst) {
|
|||
Xbyak::Label abort, end;
|
||||
|
||||
const auto src_ptr = EmitVAddrLookup(code, ctx, bitsize, abort, vaddr);
|
||||
EmitReadMemoryMov<bitsize>(code, value, src_ptr);
|
||||
EmitReadMemoryMov<bitsize>(code, value.getIdx(), src_ptr);
|
||||
code.L(end);
|
||||
|
||||
code.SwitchToFarCode();
|
||||
|
@ -279,7 +235,7 @@ void A32EmitX64::EmitMemoryWrite(A32EmitContext& ctx, IR::Inst* inst) {
|
|||
const auto dest_ptr = r13 + vaddr;
|
||||
|
||||
const auto location = code.getCurr();
|
||||
EmitWriteMemoryMov<bitsize>(code, dest_ptr, value);
|
||||
EmitWriteMemoryMov<bitsize>(code, dest_ptr, value.getIdx());
|
||||
|
||||
fastmem_patch_info.emplace(
|
||||
Common::BitCast<u64>(location),
|
||||
|
@ -298,7 +254,7 @@ void A32EmitX64::EmitMemoryWrite(A32EmitContext& ctx, IR::Inst* inst) {
|
|||
Xbyak::Label abort, end;
|
||||
|
||||
const auto dest_ptr = EmitVAddrLookup(code, ctx, bitsize, abort, vaddr);
|
||||
EmitWriteMemoryMov<bitsize>(code, dest_ptr, value);
|
||||
EmitWriteMemoryMov<bitsize>(code, dest_ptr, value.getIdx());
|
||||
code.L(end);
|
||||
|
||||
code.SwitchToFarCode();
|
||||
|
@ -418,7 +374,7 @@ void A32EmitX64::ExclusiveReadMemoryInline(A32EmitContext& ctx, IR::Inst* inst)
|
|||
const auto src_ptr = r13 + vaddr;
|
||||
|
||||
const auto location = code.getCurr();
|
||||
EmitReadMemoryMov<bitsize>(code, value, src_ptr);
|
||||
EmitReadMemoryMov<bitsize>(code, value.getIdx(), src_ptr);
|
||||
|
||||
fastmem_patch_info.emplace(
|
||||
Common::BitCast<u64>(location),
|
||||
|
@ -435,7 +391,7 @@ void A32EmitX64::ExclusiveReadMemoryInline(A32EmitContext& ctx, IR::Inst* inst)
|
|||
}
|
||||
|
||||
code.mov(tmp, Common::BitCast<u64>(GetExclusiveMonitorValuePointer(conf.global_monitor, conf.processor_id)));
|
||||
EmitWriteMemoryMov<bitsize>(code, tmp, value);
|
||||
EmitWriteMemoryMov<bitsize>(code, tmp, value.getIdx());
|
||||
|
||||
EmitExclusiveUnlock(code, conf, tmp, tmp2.cvt32());
|
||||
|
||||
|
@ -476,7 +432,7 @@ void A32EmitX64::ExclusiveWriteMemoryInline(A32EmitContext& ctx, IR::Inst* inst)
|
|||
code.mov(code.byte[r15 + offsetof(A32JitState, exclusive_state)], u8(0));
|
||||
code.mov(tmp, Common::BitCast<u64>(GetExclusiveMonitorValuePointer(conf.global_monitor, conf.processor_id)));
|
||||
|
||||
EmitReadMemoryMov<bitsize>(code, rax, tmp);
|
||||
EmitReadMemoryMov<bitsize>(code, rax.getIdx(), tmp);
|
||||
|
||||
const auto fastmem_marker = ShouldFastmem(ctx, inst);
|
||||
if (fastmem_marker) {
|
||||
|
|
|
@ -300,56 +300,6 @@ FakeCall A64EmitX64::FastmemCallback(u64 rip_) {
|
|||
};
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
template<std::size_t bitsize>
|
||||
void EmitReadMemoryMov(BlockOfCode& code, int value_idx, const Xbyak::RegExp& addr) {
|
||||
switch (bitsize) {
|
||||
case 8:
|
||||
code.movzx(Xbyak::Reg32{value_idx}, code.byte[addr]);
|
||||
return;
|
||||
case 16:
|
||||
code.movzx(Xbyak::Reg32{value_idx}, word[addr]);
|
||||
return;
|
||||
case 32:
|
||||
code.mov(Xbyak::Reg32{value_idx}, dword[addr]);
|
||||
return;
|
||||
case 64:
|
||||
code.mov(Xbyak::Reg64{value_idx}, qword[addr]);
|
||||
return;
|
||||
case 128:
|
||||
code.movups(Xbyak::Xmm{value_idx}, xword[addr]);
|
||||
return;
|
||||
default:
|
||||
ASSERT_FALSE("Invalid bitsize");
|
||||
}
|
||||
}
|
||||
|
||||
template<std::size_t bitsize>
|
||||
void EmitWriteMemoryMov(BlockOfCode& code, const Xbyak::RegExp& addr, int value_idx) {
|
||||
switch (bitsize) {
|
||||
case 8:
|
||||
code.mov(code.byte[addr], Xbyak::Reg64{value_idx}.cvt8());
|
||||
return;
|
||||
case 16:
|
||||
code.mov(word[addr], Xbyak::Reg16{value_idx});
|
||||
return;
|
||||
case 32:
|
||||
code.mov(dword[addr], Xbyak::Reg32{value_idx});
|
||||
return;
|
||||
case 64:
|
||||
code.mov(qword[addr], Xbyak::Reg64{value_idx});
|
||||
return;
|
||||
case 128:
|
||||
code.movups(xword[addr], Xbyak::Xmm{value_idx});
|
||||
return;
|
||||
default:
|
||||
ASSERT_FALSE("Invalid bitsize");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
template<std::size_t bitsize, auto callback>
|
||||
void A64EmitX64::EmitMemoryRead(A64EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
|
|
@ -197,6 +197,52 @@ template<>
|
|||
}
|
||||
}
|
||||
|
||||
template<std::size_t bitsize>
|
||||
void EmitReadMemoryMov(BlockOfCode& code, int value_idx, const Xbyak::RegExp& addr) {
|
||||
switch (bitsize) {
|
||||
case 8:
|
||||
code.movzx(Xbyak::Reg32{value_idx}, code.byte[addr]);
|
||||
return;
|
||||
case 16:
|
||||
code.movzx(Xbyak::Reg32{value_idx}, word[addr]);
|
||||
return;
|
||||
case 32:
|
||||
code.mov(Xbyak::Reg32{value_idx}, dword[addr]);
|
||||
return;
|
||||
case 64:
|
||||
code.mov(Xbyak::Reg64{value_idx}, qword[addr]);
|
||||
return;
|
||||
case 128:
|
||||
code.movups(Xbyak::Xmm{value_idx}, xword[addr]);
|
||||
return;
|
||||
default:
|
||||
ASSERT_FALSE("Invalid bitsize");
|
||||
}
|
||||
}
|
||||
|
||||
template<std::size_t bitsize>
|
||||
void EmitWriteMemoryMov(BlockOfCode& code, const Xbyak::RegExp& addr, int value_idx) {
|
||||
switch (bitsize) {
|
||||
case 8:
|
||||
code.mov(code.byte[addr], Xbyak::Reg64{value_idx}.cvt8());
|
||||
return;
|
||||
case 16:
|
||||
code.mov(word[addr], Xbyak::Reg16{value_idx});
|
||||
return;
|
||||
case 32:
|
||||
code.mov(dword[addr], Xbyak::Reg32{value_idx});
|
||||
return;
|
||||
case 64:
|
||||
code.mov(qword[addr], Xbyak::Reg64{value_idx});
|
||||
return;
|
||||
case 128:
|
||||
code.movups(xword[addr], Xbyak::Xmm{value_idx});
|
||||
return;
|
||||
default:
|
||||
ASSERT_FALSE("Invalid bitsize");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename UserConfig>
|
||||
void EmitExclusiveLock(BlockOfCode& code, const UserConfig& conf, Xbyak::Reg64 pointer, Xbyak::Reg32 tmp) {
|
||||
if (conf.HasOptimization(OptimizationFlag::Unsafe_IgnoreGlobalMonitor)) {
|
||||
|
|
Loading…
Reference in a new issue