devirtualize: Replace DEVIRT macro with function template
This commit is contained in:
parent
cd12a1862e
commit
2e0885388e
5 changed files with 76 additions and 69 deletions
|
@ -154,56 +154,56 @@ void A32EmitX64::GenMemoryAccessors() {
|
|||
code.align();
|
||||
read_memory_8 = code.getCurr<const void*>();
|
||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN);
|
||||
DEVIRT(config.callbacks, &A32::UserCallbacks::MemoryRead8).EmitCall(code);
|
||||
Devirtualize<&A32::UserCallbacks::MemoryRead8>(config.callbacks).EmitCall(code);
|
||||
ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN);
|
||||
code.ret();
|
||||
|
||||
code.align();
|
||||
read_memory_16 = code.getCurr<const void*>();
|
||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN);
|
||||
DEVIRT(config.callbacks, &A32::UserCallbacks::MemoryRead16).EmitCall(code);
|
||||
Devirtualize<&A32::UserCallbacks::MemoryRead16>(config.callbacks).EmitCall(code);
|
||||
ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN);
|
||||
code.ret();
|
||||
|
||||
code.align();
|
||||
read_memory_32 = code.getCurr<const void*>();
|
||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN);
|
||||
DEVIRT(config.callbacks, &A32::UserCallbacks::MemoryRead32).EmitCall(code);
|
||||
Devirtualize<&A32::UserCallbacks::MemoryRead32>(config.callbacks).EmitCall(code);
|
||||
ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN);
|
||||
code.ret();
|
||||
|
||||
code.align();
|
||||
read_memory_64 = code.getCurr<const void*>();
|
||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN);
|
||||
DEVIRT(config.callbacks, &A32::UserCallbacks::MemoryRead64).EmitCall(code);
|
||||
Devirtualize<&A32::UserCallbacks::MemoryRead64>(config.callbacks).EmitCall(code);
|
||||
ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN);
|
||||
code.ret();
|
||||
|
||||
code.align();
|
||||
write_memory_8 = code.getCurr<const void*>();
|
||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN);
|
||||
DEVIRT(config.callbacks, &A32::UserCallbacks::MemoryWrite8).EmitCall(code);
|
||||
Devirtualize<&A32::UserCallbacks::MemoryWrite8>(config.callbacks).EmitCall(code);
|
||||
ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN);
|
||||
code.ret();
|
||||
|
||||
code.align();
|
||||
write_memory_16 = code.getCurr<const void*>();
|
||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN);
|
||||
DEVIRT(config.callbacks, &A32::UserCallbacks::MemoryWrite16).EmitCall(code);
|
||||
Devirtualize<&A32::UserCallbacks::MemoryWrite16>(config.callbacks).EmitCall(code);
|
||||
ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN);
|
||||
code.ret();
|
||||
|
||||
code.align();
|
||||
write_memory_32 = code.getCurr<const void*>();
|
||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN);
|
||||
DEVIRT(config.callbacks, &A32::UserCallbacks::MemoryWrite32).EmitCall(code);
|
||||
Devirtualize<&A32::UserCallbacks::MemoryWrite32>(config.callbacks).EmitCall(code);
|
||||
ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN);
|
||||
code.ret();
|
||||
|
||||
code.align();
|
||||
write_memory_64 = code.getCurr<const void*>();
|
||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN);
|
||||
DEVIRT(config.callbacks, &A32::UserCallbacks::MemoryWrite64).EmitCall(code);
|
||||
Devirtualize<&A32::UserCallbacks::MemoryWrite64>(config.callbacks).EmitCall(code);
|
||||
ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN);
|
||||
code.ret();
|
||||
}
|
||||
|
@ -605,12 +605,12 @@ void A32EmitX64::EmitA32CallSupervisor(A32EmitContext& ctx, IR::Inst* inst) {
|
|||
code.SwitchMxcsrOnExit();
|
||||
code.mov(code.ABI_PARAM2, qword[r15 + offsetof(A32JitState, cycles_to_run)]);
|
||||
code.sub(code.ABI_PARAM2, qword[r15 + offsetof(A32JitState, cycles_remaining)]);
|
||||
DEVIRT(config.callbacks, &A32::UserCallbacks::AddTicks).EmitCall(code);
|
||||
Devirtualize<&A32::UserCallbacks::AddTicks>(config.callbacks).EmitCall(code);
|
||||
ctx.reg_alloc.EndOfAllocScope();
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
ctx.reg_alloc.HostCall(nullptr, {}, args[0]);
|
||||
DEVIRT(config.callbacks, &A32::UserCallbacks::CallSVC).EmitCall(code);
|
||||
DEVIRT(config.callbacks, &A32::UserCallbacks::GetTicksRemaining).EmitCall(code);
|
||||
Devirtualize<&A32::UserCallbacks::CallSVC>(config.callbacks).EmitCall(code);
|
||||
Devirtualize<&A32::UserCallbacks::GetTicksRemaining>(config.callbacks).EmitCall(code);
|
||||
code.mov(qword[r15 + offsetof(A32JitState, cycles_to_run)], code.ABI_RETURN);
|
||||
code.mov(qword[r15 + offsetof(A32JitState, cycles_remaining)], code.ABI_RETURN);
|
||||
code.SwitchMxcsrOnEntry();
|
||||
|
@ -622,7 +622,7 @@ void A32EmitX64::EmitA32ExceptionRaised(A32EmitContext& ctx, IR::Inst* inst) {
|
|||
ASSERT(args[0].IsImmediate() && args[1].IsImmediate());
|
||||
u32 pc = args[0].GetImmediateU32();
|
||||
u64 exception = args[1].GetImmediateU64();
|
||||
DEVIRT(config.callbacks, &A32::UserCallbacks::ExceptionRaised).EmitCall(code, [&](RegList param) {
|
||||
Devirtualize<&A32::UserCallbacks::ExceptionRaised>(config.callbacks).EmitCall(code, [&](RegList param) {
|
||||
code.mov(param[0], pc);
|
||||
code.mov(param[1], exception);
|
||||
});
|
||||
|
@ -691,7 +691,7 @@ static void ReadMemory(BlockOfCode& code, RegAlloc& reg_alloc, IR::Inst* inst, c
|
|||
|
||||
if (!config.page_table) {
|
||||
reg_alloc.HostCall(inst, {}, args[0]);
|
||||
DEVIRT(config.callbacks, raw_fn).EmitCall(code);
|
||||
Devirtualize<raw_fn>(config.callbacks).EmitCall(code);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -744,7 +744,7 @@ static void WriteMemory(BlockOfCode& code, RegAlloc& reg_alloc, IR::Inst* inst,
|
|||
|
||||
if (!config.page_table) {
|
||||
reg_alloc.HostCall(nullptr, {}, args[0], args[1]);
|
||||
DEVIRT(config.callbacks, raw_fn).EmitCall(code);
|
||||
Devirtualize<raw_fn>(config.callbacks).EmitCall(code);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -848,7 +848,7 @@ static void ExclusiveWrite(BlockOfCode& code, RegAlloc& reg_alloc, IR::Inst* ins
|
|||
code.shl(code.ABI_PARAM4, 32);
|
||||
code.or_(code.ABI_PARAM3, code.ABI_PARAM4);
|
||||
}
|
||||
DEVIRT(config.callbacks, fn).EmitCall(code);
|
||||
Devirtualize<fn>(config.callbacks).EmitCall(code);
|
||||
code.xor_(passed, passed);
|
||||
code.L(end);
|
||||
|
||||
|
@ -1143,7 +1143,7 @@ void A32EmitX64::EmitTerminalImpl(IR::Term::Interpret terminal, IR::LocationDesc
|
|||
code.mov(code.ABI_PARAM3.cvt32(), 1);
|
||||
code.mov(MJitStateReg(A32::Reg::PC), code.ABI_PARAM2.cvt32());
|
||||
code.SwitchMxcsrOnExit();
|
||||
DEVIRT(config.callbacks, &A32::UserCallbacks::InterpreterFallback).EmitCall(code);
|
||||
Devirtualize<&A32::UserCallbacks::InterpreterFallback>(config.callbacks).EmitCall(code);
|
||||
code.ReturnFromRunCode(true); // TODO: Check cycles
|
||||
}
|
||||
|
||||
|
|
|
@ -33,8 +33,8 @@ using namespace BackendX64;
|
|||
static RunCodeCallbacks GenRunCodeCallbacks(A32::UserCallbacks* cb, CodePtr (*LookupBlock)(void* lookup_block_arg), void* arg) {
|
||||
return RunCodeCallbacks{
|
||||
std::make_unique<ArgCallback>(LookupBlock, reinterpret_cast<u64>(arg)),
|
||||
std::make_unique<ArgCallback>(DEVIRT(cb, &A32::UserCallbacks::AddTicks)),
|
||||
std::make_unique<ArgCallback>(DEVIRT(cb, &A32::UserCallbacks::GetTicksRemaining)),
|
||||
std::make_unique<ArgCallback>(Devirtualize<&A32::UserCallbacks::AddTicks>(cb)),
|
||||
std::make_unique<ArgCallback>(Devirtualize<&A32::UserCallbacks::GetTicksRemaining>(cb)),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -140,16 +140,17 @@ void A64EmitX64::GenMemory128Accessors() {
|
|||
code.align();
|
||||
memory_read_128 = code.getCurr<void(*)()>();
|
||||
#ifdef _WIN32
|
||||
DEVIRT(conf.callbacks, &A64::UserCallbacks::MemoryRead128).EmitCallWithReturnPointer(code, [&](Xbyak::Reg64 return_value_ptr, RegList args) {
|
||||
code.mov(code.ABI_PARAM3, code.ABI_PARAM2);
|
||||
code.sub(rsp, 8 + 16 + ABI_SHADOW_SPACE);
|
||||
code.lea(return_value_ptr, ptr[rsp + ABI_SHADOW_SPACE]);
|
||||
});
|
||||
Devirtualize<&A64::UserCallbacks::MemoryRead128>(conf.callbacks).EmitCallWithReturnPointer(code,
|
||||
[&](Xbyak::Reg64 return_value_ptr, RegList args) {
|
||||
code.mov(code.ABI_PARAM3, code.ABI_PARAM2);
|
||||
code.sub(rsp, 8 + 16 + ABI_SHADOW_SPACE);
|
||||
code.lea(return_value_ptr, ptr[rsp + ABI_SHADOW_SPACE]);
|
||||
});
|
||||
code.movups(xmm1, xword[code.ABI_RETURN]);
|
||||
code.add(rsp, 8 + 16 + ABI_SHADOW_SPACE);
|
||||
#else
|
||||
code.sub(rsp, 8);
|
||||
DEVIRT(conf.callbacks, &A64::UserCallbacks::MemoryRead128).EmitCall(code);
|
||||
Devirtualize<&A64::UserCallbacks::MemoryRead128>(conf.callbacks).EmitCall(code);
|
||||
if (code.DoesCpuSupport(Xbyak::util::Cpu::tSSE41)) {
|
||||
code.movq(xmm1, code.ABI_RETURN);
|
||||
code.pinsrq(xmm1, code.ABI_RETURN2, 1);
|
||||
|
@ -168,7 +169,7 @@ void A64EmitX64::GenMemory128Accessors() {
|
|||
code.sub(rsp, 8 + 16 + ABI_SHADOW_SPACE);
|
||||
code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE]);
|
||||
code.movaps(xword[code.ABI_PARAM3], xmm1);
|
||||
DEVIRT(conf.callbacks, &A64::UserCallbacks::MemoryWrite128).EmitCall(code);
|
||||
Devirtualize<&A64::UserCallbacks::MemoryWrite128>(conf.callbacks).EmitCall(code);
|
||||
code.add(rsp, 8 + 16 + ABI_SHADOW_SPACE);
|
||||
#else
|
||||
code.sub(rsp, 8);
|
||||
|
@ -180,7 +181,7 @@ void A64EmitX64::GenMemory128Accessors() {
|
|||
code.punpckhqdq(xmm1, xmm1);
|
||||
code.movq(code.ABI_PARAM4, xmm1);
|
||||
}
|
||||
DEVIRT(conf.callbacks, &A64::UserCallbacks::MemoryWrite128).EmitCall(code);
|
||||
Devirtualize<&A64::UserCallbacks::MemoryWrite128>(conf.callbacks).EmitCall(code);
|
||||
code.add(rsp, 8);
|
||||
#endif
|
||||
code.ret();
|
||||
|
@ -189,16 +190,16 @@ void A64EmitX64::GenMemory128Accessors() {
|
|||
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::vector<std::tuple<size_t, ArgCallback>> read_callbacks {
|
||||
{8, DEVIRT(conf.callbacks, &A64::UserCallbacks::MemoryRead8)},
|
||||
{16, DEVIRT(conf.callbacks, &A64::UserCallbacks::MemoryRead16)},
|
||||
{32, DEVIRT(conf.callbacks, &A64::UserCallbacks::MemoryRead32)},
|
||||
{64, DEVIRT(conf.callbacks, &A64::UserCallbacks::MemoryRead64)},
|
||||
{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)},
|
||||
};
|
||||
const std::vector<std::tuple<size_t, ArgCallback>> write_callbacks {
|
||||
{8, DEVIRT(conf.callbacks, &A64::UserCallbacks::MemoryWrite8)},
|
||||
{16, DEVIRT(conf.callbacks, &A64::UserCallbacks::MemoryWrite16)},
|
||||
{32, DEVIRT(conf.callbacks, &A64::UserCallbacks::MemoryWrite32)},
|
||||
{64, DEVIRT(conf.callbacks, &A64::UserCallbacks::MemoryWrite64)},
|
||||
{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)},
|
||||
};
|
||||
|
||||
for (int vaddr_idx : idxes) {
|
||||
|
@ -502,9 +503,10 @@ void A64EmitX64::EmitA64CallSupervisor(A64EmitContext& ctx, IR::Inst* inst) {
|
|||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
ASSERT(args[0].IsImmediate());
|
||||
u32 imm = args[0].GetImmediateU32();
|
||||
DEVIRT(conf.callbacks, &A64::UserCallbacks::CallSVC).EmitCall(code, [&](RegList param) {
|
||||
code.mov(param[0], imm);
|
||||
});
|
||||
Devirtualize<&A64::UserCallbacks::CallSVC>(conf.callbacks).EmitCall(code,
|
||||
[&](RegList param) {
|
||||
code.mov(param[0], imm);
|
||||
});
|
||||
// The kernel would have to execute ERET to get here, which would clear exclusive state.
|
||||
code.mov(code.byte[r15 + offsetof(A64JitState, exclusive_state)], u8(0));
|
||||
}
|
||||
|
@ -515,16 +517,17 @@ void A64EmitX64::EmitA64ExceptionRaised(A64EmitContext& ctx, IR::Inst* inst) {
|
|||
ASSERT(args[0].IsImmediate() && args[1].IsImmediate());
|
||||
u64 pc = args[0].GetImmediateU64();
|
||||
u64 exception = args[1].GetImmediateU64();
|
||||
DEVIRT(conf.callbacks, &A64::UserCallbacks::ExceptionRaised).EmitCall(code, [&](RegList param) {
|
||||
code.mov(param[0], pc);
|
||||
code.mov(param[1], exception);
|
||||
});
|
||||
Devirtualize<&A64::UserCallbacks::ExceptionRaised>(conf.callbacks).EmitCall(code,
|
||||
[&](RegList param) {
|
||||
code.mov(param[0], pc);
|
||||
code.mov(param[1], exception);
|
||||
});
|
||||
}
|
||||
|
||||
void A64EmitX64::EmitA64DataCacheOperationRaised(A64EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
ctx.reg_alloc.HostCall(nullptr, args[0], args[1]);
|
||||
DEVIRT(conf.callbacks, &A64::UserCallbacks::DataCacheOperationRaised).EmitCall(code);
|
||||
Devirtualize<&A64::UserCallbacks::DataCacheOperationRaised>(conf.callbacks).EmitCall(code);
|
||||
}
|
||||
|
||||
void A64EmitX64::EmitA64DataSynchronizationBarrier(A64EmitContext&, IR::Inst*) {
|
||||
|
@ -538,7 +541,7 @@ void A64EmitX64::EmitA64DataMemoryBarrier(A64EmitContext&, IR::Inst*) {
|
|||
void A64EmitX64::EmitA64GetCNTPCT(A64EmitContext& ctx, IR::Inst* inst) {
|
||||
ctx.reg_alloc.HostCall(inst);
|
||||
code.UpdateTicks();
|
||||
DEVIRT(conf.callbacks, &A64::UserCallbacks::GetCNTPCT).EmitCall(code);
|
||||
Devirtualize<&A64::UserCallbacks::GetCNTPCT>(conf.callbacks).EmitCall(code);
|
||||
}
|
||||
|
||||
void A64EmitX64::EmitA64GetCTR(A64EmitContext& ctx, IR::Inst* inst) {
|
||||
|
@ -719,7 +722,7 @@ void A64EmitX64::EmitA64ReadMemory8(A64EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
ctx.reg_alloc.HostCall(inst, {}, args[0]);
|
||||
DEVIRT(conf.callbacks, &A64::UserCallbacks::MemoryRead8).EmitCall(code);
|
||||
Devirtualize<&A64::UserCallbacks::MemoryRead8>(conf.callbacks).EmitCall(code);
|
||||
}
|
||||
|
||||
void A64EmitX64::EmitA64ReadMemory16(A64EmitContext& ctx, IR::Inst* inst) {
|
||||
|
@ -730,7 +733,7 @@ void A64EmitX64::EmitA64ReadMemory16(A64EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
ctx.reg_alloc.HostCall(inst, {}, args[0]);
|
||||
DEVIRT(conf.callbacks, &A64::UserCallbacks::MemoryRead16).EmitCall(code);
|
||||
Devirtualize<&A64::UserCallbacks::MemoryRead16>(conf.callbacks).EmitCall(code);
|
||||
}
|
||||
|
||||
void A64EmitX64::EmitA64ReadMemory32(A64EmitContext& ctx, IR::Inst* inst) {
|
||||
|
@ -741,7 +744,7 @@ void A64EmitX64::EmitA64ReadMemory32(A64EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
ctx.reg_alloc.HostCall(inst, {}, args[0]);
|
||||
DEVIRT(conf.callbacks, &A64::UserCallbacks::MemoryRead32).EmitCall(code);
|
||||
Devirtualize<&A64::UserCallbacks::MemoryRead32>(conf.callbacks).EmitCall(code);
|
||||
}
|
||||
|
||||
void A64EmitX64::EmitA64ReadMemory64(A64EmitContext& ctx, IR::Inst* inst) {
|
||||
|
@ -752,7 +755,7 @@ void A64EmitX64::EmitA64ReadMemory64(A64EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
ctx.reg_alloc.HostCall(inst, {}, args[0]);
|
||||
DEVIRT(conf.callbacks, &A64::UserCallbacks::MemoryRead64).EmitCall(code);
|
||||
Devirtualize<&A64::UserCallbacks::MemoryRead64>(conf.callbacks).EmitCall(code);
|
||||
}
|
||||
|
||||
void A64EmitX64::EmitA64ReadMemory128(A64EmitContext& ctx, IR::Inst* inst) {
|
||||
|
@ -791,7 +794,7 @@ void A64EmitX64::EmitA64WriteMemory8(A64EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
ctx.reg_alloc.HostCall(nullptr, {}, args[0], args[1]);
|
||||
DEVIRT(conf.callbacks, &A64::UserCallbacks::MemoryWrite8).EmitCall(code);
|
||||
Devirtualize<&A64::UserCallbacks::MemoryWrite8>(conf.callbacks).EmitCall(code);
|
||||
}
|
||||
|
||||
void A64EmitX64::EmitA64WriteMemory16(A64EmitContext& ctx, IR::Inst* inst) {
|
||||
|
@ -802,7 +805,7 @@ void A64EmitX64::EmitA64WriteMemory16(A64EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
ctx.reg_alloc.HostCall(nullptr, {}, args[0], args[1]);
|
||||
DEVIRT(conf.callbacks, &A64::UserCallbacks::MemoryWrite16).EmitCall(code);
|
||||
Devirtualize<&A64::UserCallbacks::MemoryWrite16>(conf.callbacks).EmitCall(code);
|
||||
}
|
||||
|
||||
void A64EmitX64::EmitA64WriteMemory32(A64EmitContext& ctx, IR::Inst* inst) {
|
||||
|
@ -813,7 +816,7 @@ void A64EmitX64::EmitA64WriteMemory32(A64EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
ctx.reg_alloc.HostCall(nullptr, {}, args[0], args[1]);
|
||||
DEVIRT(conf.callbacks, &A64::UserCallbacks::MemoryWrite32).EmitCall(code);
|
||||
Devirtualize<&A64::UserCallbacks::MemoryWrite32>(conf.callbacks).EmitCall(code);
|
||||
}
|
||||
|
||||
void A64EmitX64::EmitA64WriteMemory64(A64EmitContext& ctx, IR::Inst* inst) {
|
||||
|
@ -824,7 +827,7 @@ void A64EmitX64::EmitA64WriteMemory64(A64EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
ctx.reg_alloc.HostCall(nullptr, {}, args[0], args[1]);
|
||||
DEVIRT(conf.callbacks, &A64::UserCallbacks::MemoryWrite64).EmitCall(code);
|
||||
Devirtualize<&A64::UserCallbacks::MemoryWrite64>(conf.callbacks).EmitCall(code);
|
||||
}
|
||||
|
||||
void A64EmitX64::EmitA64WriteMemory128(A64EmitContext& ctx, IR::Inst* inst) {
|
||||
|
@ -979,11 +982,12 @@ void A64EmitX64::EmitA64ExclusiveWriteMemory128(A64EmitContext& ctx, IR::Inst* i
|
|||
|
||||
void A64EmitX64::EmitTerminalImpl(IR::Term::Interpret terminal, IR::LocationDescriptor) {
|
||||
code.SwitchMxcsrOnExit();
|
||||
DEVIRT(conf.callbacks, &A64::UserCallbacks::InterpreterFallback).EmitCall(code, [&](RegList param) {
|
||||
code.mov(param[0], A64::LocationDescriptor{terminal.next}.PC());
|
||||
code.mov(qword[r15 + offsetof(A64JitState, pc)], param[0]);
|
||||
code.mov(param[1].cvt32(), terminal.num_instructions);
|
||||
});
|
||||
Devirtualize<&A64::UserCallbacks::InterpreterFallback>(conf.callbacks).EmitCall(code,
|
||||
[&](RegList param) {
|
||||
code.mov(param[0], A64::LocationDescriptor{terminal.next}.PC());
|
||||
code.mov(qword[r15 + offsetof(A64JitState, pc)], param[0]);
|
||||
code.mov(param[1].cvt32(), terminal.num_instructions);
|
||||
});
|
||||
code.ReturnFromRunCode(true); // TODO: Check cycles
|
||||
}
|
||||
|
||||
|
|
|
@ -29,8 +29,8 @@ using namespace BackendX64;
|
|||
static RunCodeCallbacks GenRunCodeCallbacks(A64::UserCallbacks* cb, CodePtr (*LookupBlock)(void* lookup_block_arg), void* arg) {
|
||||
return RunCodeCallbacks{
|
||||
std::make_unique<ArgCallback>(LookupBlock, reinterpret_cast<u64>(arg)),
|
||||
std::make_unique<ArgCallback>(DEVIRT(cb, &A64::UserCallbacks::AddTicks)),
|
||||
std::make_unique<ArgCallback>(DEVIRT(cb, &A64::UserCallbacks::GetTicksRemaining)),
|
||||
std::make_unique<ArgCallback>(Devirtualize<&A64::UserCallbacks::AddTicks>(cb)),
|
||||
std::make_unique<ArgCallback>(Devirtualize<&A64::UserCallbacks::GetTicksRemaining>(cb)),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -32,19 +32,19 @@ struct ThunkBuilder<R(C::*)(Args...), mfp> {
|
|||
|
||||
} // namespace impl
|
||||
|
||||
template <typename FunctionType, FunctionType mfp>
|
||||
ArgCallback DevirtualizeGeneric(Common::mp::class_type_t<FunctionType>* this_) {
|
||||
return ArgCallback{&impl::ThunkBuilder<FunctionType, mfp>::Thunk, reinterpret_cast<u64>(this_)};
|
||||
template<auto mfp>
|
||||
ArgCallback DevirtualizeGeneric(Common::mp::class_type_t<decltype(mfp)>* this_) {
|
||||
return ArgCallback{&impl::ThunkBuilder<decltype(mfp), mfp>::Thunk, reinterpret_cast<u64>(this_)};
|
||||
}
|
||||
|
||||
template <typename FunctionType, FunctionType mfp>
|
||||
ArgCallback DevirtualizeWindows(Common::mp::class_type_t<FunctionType>* this_) {
|
||||
template<auto mfp>
|
||||
ArgCallback DevirtualizeWindows(Common::mp::class_type_t<decltype(mfp)>* this_) {
|
||||
static_assert(sizeof(mfp) == 8);
|
||||
return ArgCallback{Common::BitCast<u64>(mfp), reinterpret_cast<u64>(this_)};
|
||||
}
|
||||
|
||||
template <typename FunctionType, FunctionType mfp>
|
||||
ArgCallback DevirtualizeItanium(Common::mp::class_type_t<FunctionType>* this_) {
|
||||
template<auto mfp>
|
||||
ArgCallback DevirtualizeItanium(Common::mp::class_type_t<decltype(mfp)>* this_) {
|
||||
struct MemberFunctionPointer {
|
||||
/// For a non-virtual function, this is a simple function pointer.
|
||||
/// For a virtual function, it is (1 + virtual table offset in bytes).
|
||||
|
@ -65,15 +65,18 @@ ArgCallback DevirtualizeItanium(Common::mp::class_type_t<FunctionType>* this_) {
|
|||
return ArgCallback{fn_ptr, this_ptr};
|
||||
}
|
||||
|
||||
template<auto mfp>
|
||||
ArgCallback Devirtualize(Common::mp::class_type_t<decltype(mfp)>* this_) {
|
||||
#if defined(__APPLE__) || defined(linux) || defined(__linux) || defined(__linux__)
|
||||
#define DEVIRT(this_, mfp) Dynarmic::BackendX64::DevirtualizeItanium<decltype(mfp), mfp>(this_)
|
||||
return DevirtualizeItanium<mfp>(this_);
|
||||
#elif defined(__MINGW64__)
|
||||
#define DEVIRT(this_, mfp) Dynarmic::BackendX64::DevirtualizeItanium<decltype(mfp), mfp>(this_)
|
||||
return DevirtualizeItanium<mfp>(this_);
|
||||
#elif defined(_WIN32)
|
||||
#define DEVIRT(this_, mfp) Dynarmic::BackendX64::DevirtualizeWindows<decltype(mfp), mfp>(this_)
|
||||
return DevirtualizeWindows<mfp>(this_);
|
||||
#else
|
||||
#define DEVIRT(this_, mfp) Dynarmic::BackendX64::DevirtualizeGeneric<decltype(mfp), mfp>(this_)
|
||||
return DevirtualizeGeneric<mfp>(this_);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace BackendX64
|
||||
} // namespace Dynarmic
|
||||
|
|
Loading…
Reference in a new issue