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

View file

@ -174,6 +174,16 @@ DECLARE(spu_runtime::g_gateway) = build_function_asm<spu_function_t>([](asmjit::
c.ret(); 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; DECLARE(spu_runtime::g_interpreter) = nullptr;
spu_cache::spu_cache(const std::string& loc) 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 // Fill block info
for (auto& pred : m_preds) for (auto& pred : m_preds)
{ {
@ -4331,15 +4330,6 @@ public:
m_ir->CreateRet(m_ir->CreateLoad(dispatcher)); 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 // 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 = llvm::cast<llvm::Function>(m_module->getOrInsertFunction("spu_test_state", get_ftype<void, u8*>()).getCallee());
m_test_state->setLinkage(GlobalValue::InternalLinkage); m_test_state->setLinkage(GlobalValue::InternalLinkage);
@ -4349,7 +4339,7 @@ public:
const auto escape_no = BasicBlock::Create(m_context, "", m_test_state); 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->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->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->CreateRetVoid();
m_ir->SetInsertPoint(escape_no); m_ir->SetInsertPoint(escape_no);
m_ir->CreateRetVoid(); m_ir->CreateRetVoid();

View file

@ -105,6 +105,9 @@ public:
// Recompiler entry point // Recompiler entry point
static const spu_function_t g_gateway; 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 // Interpreter entry point
static spu_function_t g_interpreter; static spu_function_t g_interpreter;