block_of_code: Make CallFunction accept function pointers only
This commit is contained in:
parent
249a2be786
commit
ea6a4e82b5
3 changed files with 36 additions and 32 deletions
|
@ -128,17 +128,6 @@ void BlockOfCode::SwitchMxcsrOnExit() {
|
||||||
ldmxcsr(dword[r15 + offsetof(JitState, save_host_MXCSR)]);
|
ldmxcsr(dword[r15 + offsetof(JitState, save_host_MXCSR)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockOfCode::CallFunction(const void* fn) {
|
|
||||||
u64 distance = u64(fn) - (getCurr<u64>() + 5);
|
|
||||||
if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) {
|
|
||||||
// Far call
|
|
||||||
mov(rax, u64(fn));
|
|
||||||
call(rax);
|
|
||||||
} else {
|
|
||||||
call(fn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlockOfCode::nop(size_t size) {
|
void BlockOfCode::nop(size_t size) {
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 0:
|
case 0:
|
||||||
|
|
|
@ -6,9 +6,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <type_traits>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <xbyak.h>
|
#include <xbyak.h>
|
||||||
|
|
||||||
#include "backend_x64/jitstate.h"
|
#include "backend_x64/jitstate.h"
|
||||||
|
@ -32,8 +30,24 @@ public:
|
||||||
void SwitchMxcsrOnEntry();
|
void SwitchMxcsrOnEntry();
|
||||||
/// Code emitter: Makes saved host MXCSR the current MXCSR
|
/// Code emitter: Makes saved host MXCSR the current MXCSR
|
||||||
void SwitchMxcsrOnExit();
|
void SwitchMxcsrOnExit();
|
||||||
|
|
||||||
/// Code emitter: Calls the function
|
/// Code emitter: Calls the function
|
||||||
void CallFunction(const void* fn);
|
template <typename FunctionPointer>
|
||||||
|
void CallFunction(FunctionPointer fn) {
|
||||||
|
static_assert(std::is_pointer<FunctionPointer>() && std::is_function<std::remove_pointer_t<FunctionPointer>>(),
|
||||||
|
"Supplied type must be a pointer to a function");
|
||||||
|
|
||||||
|
const u64 address = reinterpret_cast<u64>(fn);
|
||||||
|
const u64 distance = address - (getCurr<u64>() + 5);
|
||||||
|
|
||||||
|
if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) {
|
||||||
|
// Far call
|
||||||
|
mov(rax, address);
|
||||||
|
call(rax);
|
||||||
|
} else {
|
||||||
|
call(fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Xbyak::Address MFloatPositiveZero32() {
|
Xbyak::Address MFloatPositiveZero32() {
|
||||||
return xword[rip + consts.FloatPositiveZero32];
|
return xword[rip + consts.FloatPositiveZero32];
|
||||||
|
|
|
@ -324,7 +324,7 @@ void EmitX64::EmitCallSupervisor(IR::Block&, IR::Inst* inst) {
|
||||||
reg_alloc.HostCall(nullptr, imm32);
|
reg_alloc.HostCall(nullptr, imm32);
|
||||||
|
|
||||||
code->SwitchMxcsrOnExit();
|
code->SwitchMxcsrOnExit();
|
||||||
code->CallFunction(reinterpret_cast<void*>(cb.CallSVC));
|
code->CallFunction(cb.CallSVC);
|
||||||
code->SwitchMxcsrOnEntry();
|
code->SwitchMxcsrOnEntry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,7 +337,7 @@ void EmitX64::EmitGetFpscr(IR::Block&, IR::Inst* inst) {
|
||||||
code->mov(code->ABI_PARAM1, code->r15);
|
code->mov(code->ABI_PARAM1, code->r15);
|
||||||
|
|
||||||
code->SwitchMxcsrOnExit();
|
code->SwitchMxcsrOnExit();
|
||||||
code->CallFunction(reinterpret_cast<void*>(&GetFpscrImpl));
|
code->CallFunction(&GetFpscrImpl);
|
||||||
code->SwitchMxcsrOnEntry();
|
code->SwitchMxcsrOnEntry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,7 +352,7 @@ void EmitX64::EmitSetFpscr(IR::Block&, IR::Inst* inst) {
|
||||||
code->mov(code->ABI_PARAM2, code->r15);
|
code->mov(code->ABI_PARAM2, code->r15);
|
||||||
|
|
||||||
code->SwitchMxcsrOnExit();
|
code->SwitchMxcsrOnExit();
|
||||||
code->CallFunction(reinterpret_cast<void*>(&SetFpscrImpl));
|
code->CallFunction(&SetFpscrImpl);
|
||||||
code->SwitchMxcsrOnEntry();
|
code->SwitchMxcsrOnEntry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1832,52 +1832,53 @@ void EmitX64::EmitSetExclusive(IR::Block&, IR::Inst* inst) {
|
||||||
void EmitX64::EmitReadMemory8(IR::Block&, IR::Inst* inst) {
|
void EmitX64::EmitReadMemory8(IR::Block&, IR::Inst* inst) {
|
||||||
reg_alloc.HostCall(inst, inst->GetArg(0));
|
reg_alloc.HostCall(inst, inst->GetArg(0));
|
||||||
|
|
||||||
code->CallFunction(reinterpret_cast<void*>(cb.MemoryRead8));
|
code->CallFunction(cb.MemoryRead8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitReadMemory16(IR::Block&, IR::Inst* inst) {
|
void EmitX64::EmitReadMemory16(IR::Block&, IR::Inst* inst) {
|
||||||
reg_alloc.HostCall(inst, inst->GetArg(0));
|
reg_alloc.HostCall(inst, inst->GetArg(0));
|
||||||
|
|
||||||
code->CallFunction(reinterpret_cast<void*>(cb.MemoryRead16));
|
code->CallFunction(cb.MemoryRead16);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitReadMemory32(IR::Block&, IR::Inst* inst) {
|
void EmitX64::EmitReadMemory32(IR::Block&, IR::Inst* inst) {
|
||||||
reg_alloc.HostCall(inst, inst->GetArg(0));
|
reg_alloc.HostCall(inst, inst->GetArg(0));
|
||||||
|
|
||||||
code->CallFunction(reinterpret_cast<void*>(cb.MemoryRead32));
|
code->CallFunction(cb.MemoryRead32);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitReadMemory64(IR::Block&, IR::Inst* inst) {
|
void EmitX64::EmitReadMemory64(IR::Block&, IR::Inst* inst) {
|
||||||
reg_alloc.HostCall(inst, inst->GetArg(0));
|
reg_alloc.HostCall(inst, inst->GetArg(0));
|
||||||
|
|
||||||
code->CallFunction(reinterpret_cast<void*>(cb.MemoryRead64));
|
code->CallFunction(cb.MemoryRead64);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitWriteMemory8(IR::Block&, IR::Inst* inst) {
|
void EmitX64::EmitWriteMemory8(IR::Block&, IR::Inst* inst) {
|
||||||
reg_alloc.HostCall(nullptr, inst->GetArg(0), inst->GetArg(1));
|
reg_alloc.HostCall(nullptr, inst->GetArg(0), inst->GetArg(1));
|
||||||
|
|
||||||
code->CallFunction(reinterpret_cast<void*>(cb.MemoryWrite8));
|
code->CallFunction(cb.MemoryWrite8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitWriteMemory16(IR::Block&, IR::Inst* inst) {
|
void EmitX64::EmitWriteMemory16(IR::Block&, IR::Inst* inst) {
|
||||||
reg_alloc.HostCall(nullptr, inst->GetArg(0), inst->GetArg(1));
|
reg_alloc.HostCall(nullptr, inst->GetArg(0), inst->GetArg(1));
|
||||||
|
|
||||||
code->CallFunction(reinterpret_cast<void*>(cb.MemoryWrite16));
|
code->CallFunction(cb.MemoryWrite16);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitWriteMemory32(IR::Block&, IR::Inst* inst) {
|
void EmitX64::EmitWriteMemory32(IR::Block&, IR::Inst* inst) {
|
||||||
reg_alloc.HostCall(nullptr, inst->GetArg(0), inst->GetArg(1));
|
reg_alloc.HostCall(nullptr, inst->GetArg(0), inst->GetArg(1));
|
||||||
|
|
||||||
code->CallFunction(reinterpret_cast<void*>(cb.MemoryWrite32));
|
code->CallFunction(cb.MemoryWrite32);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitWriteMemory64(IR::Block&, IR::Inst* inst) {
|
void EmitX64::EmitWriteMemory64(IR::Block&, IR::Inst* inst) {
|
||||||
reg_alloc.HostCall(nullptr, inst->GetArg(0), inst->GetArg(1));
|
reg_alloc.HostCall(nullptr, inst->GetArg(0), inst->GetArg(1));
|
||||||
|
|
||||||
code->CallFunction(reinterpret_cast<void*>(cb.MemoryWrite64));
|
code->CallFunction(cb.MemoryWrite64);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ExclusiveWrite(BlockOfCode* code, RegAlloc& reg_alloc, IR::Inst* inst, void* fn) {
|
template <typename FunctionPointer>
|
||||||
|
static void ExclusiveWrite(BlockOfCode* code, RegAlloc& reg_alloc, IR::Inst* inst, FunctionPointer fn) {
|
||||||
using namespace Xbyak::util;
|
using namespace Xbyak::util;
|
||||||
Xbyak::Label end;
|
Xbyak::Label end;
|
||||||
|
|
||||||
|
@ -1899,15 +1900,15 @@ static void ExclusiveWrite(BlockOfCode* code, RegAlloc& reg_alloc, IR::Inst* ins
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitExclusiveWriteMemory8(IR::Block&, IR::Inst* inst) {
|
void EmitX64::EmitExclusiveWriteMemory8(IR::Block&, IR::Inst* inst) {
|
||||||
ExclusiveWrite(code, reg_alloc, inst, reinterpret_cast<void*>(cb.MemoryWrite8));
|
ExclusiveWrite(code, reg_alloc, inst, cb.MemoryWrite8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitExclusiveWriteMemory16(IR::Block&, IR::Inst* inst) {
|
void EmitX64::EmitExclusiveWriteMemory16(IR::Block&, IR::Inst* inst) {
|
||||||
ExclusiveWrite(code, reg_alloc, inst, reinterpret_cast<void*>(cb.MemoryWrite16));
|
ExclusiveWrite(code, reg_alloc, inst, cb.MemoryWrite16);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitExclusiveWriteMemory32(IR::Block&, IR::Inst* inst) {
|
void EmitX64::EmitExclusiveWriteMemory32(IR::Block&, IR::Inst* inst) {
|
||||||
ExclusiveWrite(code, reg_alloc, inst, reinterpret_cast<void*>(cb.MemoryWrite32));
|
ExclusiveWrite(code, reg_alloc, inst, cb.MemoryWrite32);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitExclusiveWriteMemory64(IR::Block&, IR::Inst* inst) {
|
void EmitX64::EmitExclusiveWriteMemory64(IR::Block&, IR::Inst* inst) {
|
||||||
|
@ -1931,7 +1932,7 @@ void EmitX64::EmitExclusiveWriteMemory64(IR::Block&, IR::Inst* inst) {
|
||||||
code->mov(value.cvt32(), value.cvt32()); // zero extend to 64-bits
|
code->mov(value.cvt32(), value.cvt32()); // zero extend to 64-bits
|
||||||
code->shl(value_hi, 32);
|
code->shl(value_hi, 32);
|
||||||
code->or_(value, value_hi);
|
code->or_(value, value_hi);
|
||||||
code->CallFunction(reinterpret_cast<void*>(cb.MemoryWrite64));
|
code->CallFunction(cb.MemoryWrite64);
|
||||||
code->xor_(passed, passed);
|
code->xor_(passed, passed);
|
||||||
code->L(end);
|
code->L(end);
|
||||||
}
|
}
|
||||||
|
@ -2107,7 +2108,7 @@ void EmitX64::EmitTerminalInterpret(IR::Term::Interpret terminal, Arm::LocationD
|
||||||
code->mov(code->ABI_PARAM2, reinterpret_cast<u64>(jit_interface));
|
code->mov(code->ABI_PARAM2, reinterpret_cast<u64>(jit_interface));
|
||||||
code->mov(MJitStateReg(Arm::Reg::PC), code->ABI_PARAM1.cvt32());
|
code->mov(MJitStateReg(Arm::Reg::PC), code->ABI_PARAM1.cvt32());
|
||||||
code->SwitchMxcsrOnExit();
|
code->SwitchMxcsrOnExit();
|
||||||
code->CallFunction(reinterpret_cast<void*>(cb.InterpreterFallback));
|
code->CallFunction(cb.InterpreterFallback);
|
||||||
code->ReturnFromRunCode(false); // TODO: Check cycles
|
code->ReturnFromRunCode(false); // TODO: Check cycles
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue