|
|
@ -115,16 +115,16 @@ void A64EmitX64::GenMemory128Accessors() { |
|
|
void A64EmitX64::GenFastmemFallbacks() { |
|
|
void A64EmitX64::GenFastmemFallbacks() { |
|
|
const std::initializer_list<int> idxes{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; |
|
|
const std::initializer_list<int> idxes{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; |
|
|
const std::array<std::pair<size_t, ArgCallback>, 4> read_callbacks{{ |
|
|
const std::array<std::pair<size_t, ArgCallback>, 4> read_callbacks{{ |
|
|
{8, Devirtualize<&A64::UserCallbacks::MemoryRead8>(conf.callbacks)}, |
|
|
|
|
|
{16, Devirtualize<&A64::UserCallbacks::MemoryRead16>(conf.callbacks)}, |
|
|
|
|
|
{32, Devirtualize<&A64::UserCallbacks::MemoryRead32>(conf.callbacks)}, |
|
|
|
|
|
{64, Devirtualize<&A64::UserCallbacks::MemoryRead64>(conf.callbacks)}, |
|
|
|
|
|
|
|
|
{8, Devirtualize<&A64::UserCallbacks::MemoryRead>(conf.callbacks)}, |
|
|
|
|
|
{16, Devirtualize<&A64::UserCallbacks::MemoryRead>(conf.callbacks)}, |
|
|
|
|
|
{32, Devirtualize<&A64::UserCallbacks::MemoryRead>(conf.callbacks)}, |
|
|
|
|
|
{64, Devirtualize<&A64::UserCallbacks::MemoryRead>(conf.callbacks)}, |
|
|
}}; |
|
|
}}; |
|
|
const std::array<std::pair<size_t, ArgCallback>, 4> write_callbacks{{ |
|
|
const std::array<std::pair<size_t, ArgCallback>, 4> write_callbacks{{ |
|
|
{8, Devirtualize<&A64::UserCallbacks::MemoryWrite8>(conf.callbacks)}, |
|
|
|
|
|
{16, Devirtualize<&A64::UserCallbacks::MemoryWrite16>(conf.callbacks)}, |
|
|
|
|
|
{32, Devirtualize<&A64::UserCallbacks::MemoryWrite32>(conf.callbacks)}, |
|
|
|
|
|
{64, Devirtualize<&A64::UserCallbacks::MemoryWrite64>(conf.callbacks)}, |
|
|
|
|
|
|
|
|
{8, Devirtualize<&A64::UserCallbacks::MemoryWrite>(conf.callbacks)}, |
|
|
|
|
|
{16, Devirtualize<&A64::UserCallbacks::MemoryWrite>(conf.callbacks)}, |
|
|
|
|
|
{32, Devirtualize<&A64::UserCallbacks::MemoryWrite>(conf.callbacks)}, |
|
|
|
|
|
{64, Devirtualize<&A64::UserCallbacks::MemoryWrite>(conf.callbacks)}, |
|
|
}}; |
|
|
}}; |
|
|
const std::array<std::pair<size_t, ArgCallback>, 4> exclusive_write_callbacks{{ |
|
|
const std::array<std::pair<size_t, ArgCallback>, 4> exclusive_write_callbacks{{ |
|
|
{8, Devirtualize<&A64::UserCallbacks::MemoryWriteExclusive8>(conf.callbacks)}, |
|
|
{8, Devirtualize<&A64::UserCallbacks::MemoryWriteExclusive8>(conf.callbacks)}, |
|
|
@ -204,12 +204,12 @@ void A64EmitX64::GenFastmemFallbacks() { |
|
|
code.align(); |
|
|
code.align(); |
|
|
read_fallbacks[std::make_tuple(ordered, bitsize, vaddr_idx, value_idx)] = code.getCurr<void (*)()>(); |
|
|
read_fallbacks[std::make_tuple(ordered, bitsize, vaddr_idx, value_idx)] = code.getCurr<void (*)()>(); |
|
|
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocRegIdx(value_idx)); |
|
|
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocRegIdx(value_idx)); |
|
|
|
|
|
// params = { this, vaddr, size }
|
|
|
if (vaddr_idx != code.ABI_PARAM2.getIdx()) { |
|
|
if (vaddr_idx != code.ABI_PARAM2.getIdx()) { |
|
|
code.mov(code.ABI_PARAM2, Xbyak::Reg64{vaddr_idx}); |
|
|
code.mov(code.ABI_PARAM2, Xbyak::Reg64{vaddr_idx}); |
|
|
} |
|
|
} |
|
|
if (ordered) { |
|
|
|
|
|
code.mfence(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
code.mov(code.ABI_PARAM3, bitsize / CHAR_BIT); |
|
|
|
|
|
if (ordered) code.mfence(); |
|
|
callback.EmitCall(code); |
|
|
callback.EmitCall(code); |
|
|
if (value_idx != code.ABI_RETURN.getIdx()) { |
|
|
if (value_idx != code.ABI_RETURN.getIdx()) { |
|
|
code.mov(Xbyak::Reg64{value_idx}, code.ABI_RETURN); |
|
|
code.mov(Xbyak::Reg64{value_idx}, code.ABI_RETURN); |
|
|
@ -224,6 +224,7 @@ void A64EmitX64::GenFastmemFallbacks() { |
|
|
code.align(); |
|
|
code.align(); |
|
|
write_fallbacks[std::make_tuple(ordered, bitsize, vaddr_idx, value_idx)] = code.getCurr<void (*)()>(); |
|
|
write_fallbacks[std::make_tuple(ordered, bitsize, vaddr_idx, value_idx)] = code.getCurr<void (*)()>(); |
|
|
ABI_PushCallerSaveRegistersAndAdjustStack(code); |
|
|
ABI_PushCallerSaveRegistersAndAdjustStack(code); |
|
|
|
|
|
// params = { this, vaddr, value, size }
|
|
|
if (vaddr_idx == code.ABI_PARAM3.getIdx() && value_idx == code.ABI_PARAM2.getIdx()) { |
|
|
if (vaddr_idx == code.ABI_PARAM3.getIdx() && value_idx == code.ABI_PARAM2.getIdx()) { |
|
|
code.xchg(code.ABI_PARAM2, code.ABI_PARAM3); |
|
|
code.xchg(code.ABI_PARAM2, code.ABI_PARAM3); |
|
|
} else if (vaddr_idx == code.ABI_PARAM3.getIdx()) { |
|
|
} else if (vaddr_idx == code.ABI_PARAM3.getIdx()) { |
|
|
@ -240,10 +241,9 @@ void A64EmitX64::GenFastmemFallbacks() { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
code.ZeroExtendFrom(bitsize, code.ABI_PARAM3); |
|
|
code.ZeroExtendFrom(bitsize, code.ABI_PARAM3); |
|
|
|
|
|
code.mov(code.ABI_PARAM4, bitsize / CHAR_BIT); |
|
|
callback.EmitCall(code); |
|
|
callback.EmitCall(code); |
|
|
if (ordered) { |
|
|
|
|
|
code.mfence(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (ordered) code.mfence(); |
|
|
ABI_PopCallerSaveRegistersAndAdjustStack(code); |
|
|
ABI_PopCallerSaveRegistersAndAdjustStack(code); |
|
|
code.ret(); |
|
|
code.ret(); |
|
|
PerfMapRegister(write_fallbacks[std::make_tuple(ordered, bitsize, vaddr_idx, value_idx)], code.getCurr(), fmt::format("a64_write_fallback_{}", bitsize)); |
|
|
PerfMapRegister(write_fallbacks[std::make_tuple(ordered, bitsize, vaddr_idx, value_idx)], code.getCurr(), fmt::format("a64_write_fallback_{}", bitsize)); |
|
|
@ -286,19 +286,19 @@ void A64EmitX64::GenFastmemFallbacks() { |
|
|
#undef Axx
|
|
|
#undef Axx
|
|
|
|
|
|
|
|
|
void A64EmitX64::EmitA64ReadMemory8(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
void A64EmitX64::EmitA64ReadMemory8(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
EmitMemoryRead<8, &A64::UserCallbacks::MemoryRead8>(ctx, inst); |
|
|
|
|
|
|
|
|
EmitMemoryRead<8, &A64::UserCallbacks::MemoryRead>(ctx, inst); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void A64EmitX64::EmitA64ReadMemory16(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
void A64EmitX64::EmitA64ReadMemory16(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
EmitMemoryRead<16, &A64::UserCallbacks::MemoryRead16>(ctx, inst); |
|
|
|
|
|
|
|
|
EmitMemoryRead<16, &A64::UserCallbacks::MemoryRead>(ctx, inst); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void A64EmitX64::EmitA64ReadMemory32(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
void A64EmitX64::EmitA64ReadMemory32(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
EmitMemoryRead<32, &A64::UserCallbacks::MemoryRead32>(ctx, inst); |
|
|
|
|
|
|
|
|
EmitMemoryRead<32, &A64::UserCallbacks::MemoryRead>(ctx, inst); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void A64EmitX64::EmitA64ReadMemory64(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
void A64EmitX64::EmitA64ReadMemory64(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
EmitMemoryRead<64, &A64::UserCallbacks::MemoryRead64>(ctx, inst); |
|
|
|
|
|
|
|
|
EmitMemoryRead<64, &A64::UserCallbacks::MemoryRead>(ctx, inst); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void A64EmitX64::EmitA64ReadMemory128(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
void A64EmitX64::EmitA64ReadMemory128(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
@ -306,23 +306,23 @@ void A64EmitX64::EmitA64ReadMemory128(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void A64EmitX64::EmitA64WriteMemory8(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
void A64EmitX64::EmitA64WriteMemory8(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
EmitMemoryWrite<8, &A64::UserCallbacks::MemoryWrite8>(ctx, inst); |
|
|
|
|
|
|
|
|
EmitMemoryWrite<8, &A64::UserCallbacks::MemoryWrite>(ctx, inst); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void A64EmitX64::EmitA64WriteMemory16(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
void A64EmitX64::EmitA64WriteMemory16(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
EmitMemoryWrite<16, &A64::UserCallbacks::MemoryWrite16>(ctx, inst); |
|
|
|
|
|
|
|
|
EmitMemoryWrite<16, &A64::UserCallbacks::MemoryWrite>(ctx, inst); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void A64EmitX64::EmitA64WriteMemory32(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
void A64EmitX64::EmitA64WriteMemory32(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
EmitMemoryWrite<32, &A64::UserCallbacks::MemoryWrite32>(ctx, inst); |
|
|
|
|
|
|
|
|
EmitMemoryWrite<32, &A64::UserCallbacks::MemoryWrite>(ctx, inst); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void A64EmitX64::EmitA64WriteMemory64(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
void A64EmitX64::EmitA64WriteMemory64(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
EmitMemoryWrite<64, &A64::UserCallbacks::MemoryWrite64>(ctx, inst); |
|
|
|
|
|
|
|
|
EmitMemoryWrite<64, &A64::UserCallbacks::MemoryWrite>(ctx, inst); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void A64EmitX64::EmitA64WriteMemory128(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
void A64EmitX64::EmitA64WriteMemory128(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
EmitMemoryWrite<128, &A64::UserCallbacks::MemoryWrite64>(ctx, inst); |
|
|
|
|
|
|
|
|
EmitMemoryWrite<128, &A64::UserCallbacks::MemoryWrite>(ctx, inst); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void A64EmitX64::EmitA64ClearExclusive(A64EmitContext&, IR::Inst*) { |
|
|
void A64EmitX64::EmitA64ClearExclusive(A64EmitContext&, IR::Inst*) { |
|
|
@ -331,33 +331,33 @@ void A64EmitX64::EmitA64ClearExclusive(A64EmitContext&, IR::Inst*) { |
|
|
|
|
|
|
|
|
void A64EmitX64::EmitA64ExclusiveReadMemory8(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
void A64EmitX64::EmitA64ExclusiveReadMemory8(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
if (conf.fastmem_exclusive_access) { |
|
|
if (conf.fastmem_exclusive_access) { |
|
|
EmitExclusiveReadMemoryInline<8, &A64::UserCallbacks::MemoryRead8>(ctx, inst); |
|
|
|
|
|
|
|
|
EmitExclusiveReadMemoryInline<8, &A64::UserCallbacks::MemoryRead>(ctx, inst); |
|
|
} else { |
|
|
} else { |
|
|
EmitExclusiveReadMemory<8, &A64::UserCallbacks::MemoryRead8>(ctx, inst); |
|
|
|
|
|
|
|
|
EmitExclusiveReadMemory<8, &A64::UserCallbacks::MemoryRead>(ctx, inst); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void A64EmitX64::EmitA64ExclusiveReadMemory16(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
void A64EmitX64::EmitA64ExclusiveReadMemory16(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
if (conf.fastmem_exclusive_access) { |
|
|
if (conf.fastmem_exclusive_access) { |
|
|
EmitExclusiveReadMemoryInline<16, &A64::UserCallbacks::MemoryRead16>(ctx, inst); |
|
|
|
|
|
|
|
|
EmitExclusiveReadMemoryInline<16, &A64::UserCallbacks::MemoryRead>(ctx, inst); |
|
|
} else { |
|
|
} else { |
|
|
EmitExclusiveReadMemory<16, &A64::UserCallbacks::MemoryRead16>(ctx, inst); |
|
|
|
|
|
|
|
|
EmitExclusiveReadMemory<16, &A64::UserCallbacks::MemoryRead>(ctx, inst); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void A64EmitX64::EmitA64ExclusiveReadMemory32(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
void A64EmitX64::EmitA64ExclusiveReadMemory32(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
if (conf.fastmem_exclusive_access) { |
|
|
if (conf.fastmem_exclusive_access) { |
|
|
EmitExclusiveReadMemoryInline<32, &A64::UserCallbacks::MemoryRead32>(ctx, inst); |
|
|
|
|
|
|
|
|
EmitExclusiveReadMemoryInline<32, &A64::UserCallbacks::MemoryRead>(ctx, inst); |
|
|
} else { |
|
|
} else { |
|
|
EmitExclusiveReadMemory<32, &A64::UserCallbacks::MemoryRead32>(ctx, inst); |
|
|
|
|
|
|
|
|
EmitExclusiveReadMemory<32, &A64::UserCallbacks::MemoryRead>(ctx, inst); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void A64EmitX64::EmitA64ExclusiveReadMemory64(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
void A64EmitX64::EmitA64ExclusiveReadMemory64(A64EmitContext& ctx, IR::Inst* inst) { |
|
|
if (conf.fastmem_exclusive_access) { |
|
|
if (conf.fastmem_exclusive_access) { |
|
|
EmitExclusiveReadMemoryInline<64, &A64::UserCallbacks::MemoryRead64>(ctx, inst); |
|
|
|
|
|
|
|
|
EmitExclusiveReadMemoryInline<64, &A64::UserCallbacks::MemoryRead>(ctx, inst); |
|
|
} else { |
|
|
} else { |
|
|
EmitExclusiveReadMemory<64, &A64::UserCallbacks::MemoryRead64>(ctx, inst); |
|
|
|
|
|
|
|
|
EmitExclusiveReadMemory<64, &A64::UserCallbacks::MemoryRead>(ctx, inst); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|