block_of_code: Make CallFunction accept function pointers only

This commit is contained in:
Lioncash 2016-08-31 16:09:26 -04:00 committed by MerryMage
parent 249a2be786
commit ea6a4e82b5
3 changed files with 36 additions and 32 deletions

View file

@ -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:

View file

@ -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];

View file

@ -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
} }