SPU ASMJIT: add PIC support (fix)

Also cleanup and adapt for GHC CC.
This commit is contained in:
Nekotekina 2019-05-13 21:17:31 +03:00
parent 82295d131a
commit c481472faf
4 changed files with 336 additions and 359 deletions

File diff suppressed because it is too large Load Diff

View File

@ -19,18 +19,26 @@ private:
// ASMJIT runtime
::jit_runtime m_asmrt;
u32 m_base;
// emitter:
asmjit::X86Assembler* c;
// arguments:
const asmjit::X86Gp* cpu;
const asmjit::X86Gp* ls;
const asmjit::X86Gp* rip;
const asmjit::X86Gp* pc0;
// Native args or temp variables:
const asmjit::X86Gp* arg0;
const asmjit::X86Gp* arg1;
const asmjit::X86Gp* qw0;
const asmjit::X86Gp* qw1;
// temporary:
const asmjit::X86Gp* addr;
std::array<const asmjit::X86Xmm*, 6> vec;
std::array<const asmjit::X86Xmm*, 16> vec;
// workload for the end of function:
std::vector<std::function<void()>> after;
@ -81,12 +89,11 @@ private:
asmjit::X86Mem XmmConst(__m128 data);
asmjit::X86Mem XmmConst(__m128i data);
asmjit::X86Mem get_pc(u32 addr);
void branch_fixed(u32 target);
void branch_indirect(spu_opcode_t op, bool jt = false, bool ret = true);
void branch_set_link(u32 target);
void fall(spu_opcode_t op);
void save_rcx();
void load_rcx();
void get_events();

View File

@ -174,6 +174,16 @@ DECLARE(spu_runtime::g_gateway) = build_function_asm<spu_function_t>([](asmjit::
c.ret();
});
DECLARE(spu_runtime::g_escape) = build_function_asm<void(*)(spu_thread*)>([](asmjit::X86Assembler& c, auto& args)
{
using namespace asmjit;
// Restore native stack pointer (longjmp emulation)
c.mov(x86::rsp, x86::qword_ptr(args[0], ::offset32(&spu_thread::saved_native_sp)));
c.sub(x86::rsp, 8);
c.ret();
});
DECLARE(spu_runtime::g_interpreter) = nullptr;
spu_cache::spu_cache(const std::string& loc)
@ -2062,17 +2072,6 @@ const std::vector<u32>& spu_recompiler_base::analyse(const be_t<u32>* ls, u32 en
}
}
// Skip some steps for asmjit
if (g_cfg.core.spu_decoder == spu_decoder_type::asmjit)
{
if (result.size() == 1)
{
result.clear();
}
return result;
}
// Fill block info
for (auto& pred : m_preds)
{
@ -4331,15 +4330,6 @@ public:
m_ir->CreateRet(m_ir->CreateLoad(dispatcher));
}
// Longjmp analogue (restore saved host thread's stack pointer)
const auto escape = llvm::cast<llvm::Function>(m_module->getOrInsertFunction("spu_escape", get_ftype<void, u8*>()).getCallee());
escape->setLinkage(GlobalValue::InternalLinkage);
m_ir->SetInsertPoint(BasicBlock::Create(m_context, "", escape));
const auto load_sp = m_ir->CreateLoad(_ptr<u64>(&*escape->arg_begin(), ::offset32(&spu_thread::saved_native_sp)));
const auto rsp_name = MetadataAsValue::get(m_context, MDNode::get(m_context, {MDString::get(m_context, "rsp")}));
m_ir->CreateCall(get_intrinsic<u64>(Intrinsic::write_register), {rsp_name, m_ir->CreateSub(load_sp, m_ir->getInt64(8))});
m_ir->CreateRetVoid();
// Function that executes check_state and escapes if necessary
m_test_state = llvm::cast<llvm::Function>(m_module->getOrInsertFunction("spu_test_state", get_ftype<void, u8*>()).getCallee());
m_test_state->setLinkage(GlobalValue::InternalLinkage);
@ -4349,7 +4339,7 @@ public:
const auto escape_no = BasicBlock::Create(m_context, "", m_test_state);
m_ir->CreateCondBr(call("spu_exec_check_state", &exec_check_state, &*m_test_state->arg_begin()), escape_yes, escape_no);
m_ir->SetInsertPoint(escape_yes);
m_ir->CreateCall(escape, {&*m_test_state->arg_begin()});
call("spu_escape", spu_runtime::g_escape, &*m_test_state->arg_begin());
m_ir->CreateRetVoid();
m_ir->SetInsertPoint(escape_no);
m_ir->CreateRetVoid();

View File

@ -105,6 +105,9 @@ public:
// Recompiler entry point
static const spu_function_t g_gateway;
// Longjmp to the end of the gateway function (native CC)
static void(*const g_escape)(spu_thread*);
// Interpreter entry point
static spu_function_t g_interpreter;