a64/fastmem: Implement fastmem on 128 bit memory access.
This commit is contained in:
parent
ff01b1c6f9
commit
e82685223a
1 changed files with 95 additions and 42 deletions
|
@ -1082,31 +1082,57 @@ void A64EmitX64::EmitA64ReadMemory64(A64EmitContext& ctx, IR::Inst* inst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void A64EmitX64::EmitA64ReadMemory128(A64EmitContext& ctx, IR::Inst* inst) {
|
void A64EmitX64::EmitA64ReadMemory128(A64EmitContext& ctx, IR::Inst* inst) {
|
||||||
if (conf.page_table) {
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
Xbyak::Label abort, end;
|
const auto fastmem_marker = ShouldFastmem(ctx, inst);
|
||||||
|
|
||||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
if (!conf.page_table && !fastmem_marker) {
|
||||||
const Xbyak::Reg64 vaddr = ctx.reg_alloc.UseGpr(args[0]);
|
// Neither fastmem nor page table: Use callbacks
|
||||||
const Xbyak::Xmm value = ctx.reg_alloc.ScratchXmm();
|
ctx.reg_alloc.HostCall(nullptr, {}, args[0]);
|
||||||
|
code.CallFunction(memory_read_128);
|
||||||
const auto src_ptr = EmitVAddrLookup(code, ctx, 128, abort, vaddr);
|
ctx.reg_alloc.DefineValue(inst, xmm1);
|
||||||
code.movups(value, xword[src_ptr]);
|
|
||||||
code.L(end);
|
|
||||||
|
|
||||||
code.SwitchToFarCode();
|
|
||||||
code.L(abort);
|
|
||||||
code.call(read_fallbacks[std::make_tuple(128, vaddr.getIdx(), value.getIdx())]);
|
|
||||||
code.jmp(end, code.T_NEAR);
|
|
||||||
code.SwitchToNearCode();
|
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(inst, value);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
const Xbyak::Reg64 vaddr = ctx.reg_alloc.UseGpr(args[0]);
|
||||||
ctx.reg_alloc.HostCall(nullptr, {}, args[0]);
|
const Xbyak::Xmm value = ctx.reg_alloc.ScratchXmm();
|
||||||
code.CallFunction(memory_read_128);
|
|
||||||
ctx.reg_alloc.DefineValue(inst, xmm1);
|
const auto wrapped_fn = read_fallbacks[std::make_tuple(128, vaddr.getIdx(), value.getIdx())];
|
||||||
|
|
||||||
|
Xbyak::Label abort, end;
|
||||||
|
bool require_abort_handling = false;
|
||||||
|
|
||||||
|
if (fastmem_marker) {
|
||||||
|
// Use fastmem
|
||||||
|
const auto src_ptr = EmitFastmemVAddr(code, ctx, abort, vaddr, require_abort_handling);
|
||||||
|
|
||||||
|
const auto location = code.getCurr();
|
||||||
|
code.movups(value, xword[src_ptr]);
|
||||||
|
|
||||||
|
fastmem_patch_info.emplace(
|
||||||
|
Common::BitCast<u64>(location),
|
||||||
|
FastmemPatchInfo{
|
||||||
|
Common::BitCast<u64>(code.getCurr()),
|
||||||
|
Common::BitCast<u64>(wrapped_fn),
|
||||||
|
*fastmem_marker,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Use page table
|
||||||
|
ASSERT(conf.page_table);
|
||||||
|
const auto src_ptr = EmitVAddrLookup(code, ctx, 128, abort, vaddr);
|
||||||
|
code.movups(value, xword[src_ptr]);
|
||||||
|
}
|
||||||
|
code.L(end);
|
||||||
|
|
||||||
|
if (require_abort_handling) {
|
||||||
|
code.SwitchToFarCode();
|
||||||
|
code.L(abort);
|
||||||
|
code.call(wrapped_fn);
|
||||||
|
code.jmp(end, code.T_NEAR);
|
||||||
|
code.SwitchToNearCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.reg_alloc.DefineValue(inst, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void A64EmitX64::EmitA64WriteMemory8(A64EmitContext& ctx, IR::Inst* inst) {
|
void A64EmitX64::EmitA64WriteMemory8(A64EmitContext& ctx, IR::Inst* inst) {
|
||||||
|
@ -1126,31 +1152,58 @@ void A64EmitX64::EmitA64WriteMemory64(A64EmitContext& ctx, IR::Inst* inst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void A64EmitX64::EmitA64WriteMemory128(A64EmitContext& ctx, IR::Inst* inst) {
|
void A64EmitX64::EmitA64WriteMemory128(A64EmitContext& ctx, IR::Inst* inst) {
|
||||||
if (conf.page_table) {
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
Xbyak::Label abort, end;
|
const auto fastmem_marker = ShouldFastmem(ctx, inst);
|
||||||
|
|
||||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
if (!conf.page_table && !fastmem_marker) {
|
||||||
const Xbyak::Reg64 vaddr = ctx.reg_alloc.UseGpr(args[0]);
|
// Neither fastmem nor page table: Use callbacks
|
||||||
const Xbyak::Xmm value = ctx.reg_alloc.UseXmm(args[1]);
|
ctx.reg_alloc.Use(args[0], ABI_PARAM2);
|
||||||
|
ctx.reg_alloc.Use(args[1], HostLoc::XMM1);
|
||||||
const auto dest_ptr = EmitVAddrLookup(code, ctx, 128, abort, vaddr);
|
ctx.reg_alloc.EndOfAllocScope();
|
||||||
code.movups(xword[dest_ptr], value);
|
ctx.reg_alloc.HostCall(nullptr);
|
||||||
code.L(end);
|
code.CallFunction(memory_write_128);
|
||||||
|
|
||||||
code.SwitchToFarCode();
|
|
||||||
code.L(abort);
|
|
||||||
code.call(write_fallbacks[std::make_tuple(128, vaddr.getIdx(), value.getIdx())]);
|
|
||||||
code.jmp(end, code.T_NEAR);
|
|
||||||
code.SwitchToNearCode();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
const Xbyak::Reg64 vaddr = ctx.reg_alloc.UseGpr(args[0]);
|
||||||
ctx.reg_alloc.Use(args[0], ABI_PARAM2);
|
const Xbyak::Xmm value = ctx.reg_alloc.UseXmm(args[1]);
|
||||||
ctx.reg_alloc.Use(args[1], HostLoc::XMM1);
|
|
||||||
ctx.reg_alloc.EndOfAllocScope();
|
const auto wrapped_fn = write_fallbacks[std::make_tuple(128, vaddr.getIdx(), value.getIdx())];
|
||||||
ctx.reg_alloc.HostCall(nullptr);
|
|
||||||
code.CallFunction(memory_write_128);
|
Xbyak::Label abort, end;
|
||||||
|
bool require_abort_handling = false;
|
||||||
|
|
||||||
|
if (fastmem_marker) {
|
||||||
|
// Use fastmem
|
||||||
|
const auto dest_ptr = EmitFastmemVAddr(code, ctx, abort, vaddr, require_abort_handling);
|
||||||
|
|
||||||
|
const auto location = code.getCurr();
|
||||||
|
code.movups(xword[dest_ptr], value);
|
||||||
|
|
||||||
|
fastmem_patch_info.emplace(
|
||||||
|
Common::BitCast<u64>(location),
|
||||||
|
FastmemPatchInfo{
|
||||||
|
Common::BitCast<u64>(code.getCurr()),
|
||||||
|
Common::BitCast<u64>(wrapped_fn),
|
||||||
|
*fastmem_marker,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Use page table
|
||||||
|
ASSERT(conf.page_table);
|
||||||
|
const auto dest_ptr = EmitVAddrLookup(code, ctx, 128, abort, vaddr);
|
||||||
|
require_abort_handling = true;
|
||||||
|
code.movups(xword[dest_ptr], value);
|
||||||
|
}
|
||||||
|
code.L(end);
|
||||||
|
|
||||||
|
if (require_abort_handling) {
|
||||||
|
code.SwitchToFarCode();
|
||||||
|
code.L(abort);
|
||||||
|
code.call(wrapped_fn);
|
||||||
|
code.jmp(end, code.T_NEAR);
|
||||||
|
code.SwitchToNearCode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<std::size_t bitsize, auto callback>
|
template<std::size_t bitsize, auto callback>
|
||||||
|
|
Loading…
Reference in a new issue