Very basic, super slow, nasty indirection.

This commit is contained in:
Ben Vanik
2013-05-25 20:32:58 -07:00
parent 2986a0be82
commit 4073028188
11 changed files with 113 additions and 63 deletions

View File

@@ -450,10 +450,21 @@ void X64Emitter::GenerateSharedBlocks() {
SpillRegisters();
X86CompilerFuncCall* call = c.call(global_exports_.XeIndirectBranch);
call->setPrototype(kX86FuncConvDefault,
FuncBuilder3<void, void*, uint64_t, uint64_t>());
FuncBuilder3<void*, void*, uint64_t, uint64_t>());
call->setArgument(0, c.getGpArg(0));
call->setArgument(1, locals_.indirection_target);
call->setArgument(2, locals_.indirection_cia);
GpVar target_ptr(c.newGpVar());
call->setReturn(target_ptr);
// Call target.
// void fn(ppc_state*, uint64_t)
call = c.call(target_ptr);
call->setComment("Indirection branch");
call->setPrototype(kX86FuncConvDefault,
FuncBuilder2<void, void*, uint64_t>());
call->setArgument(0, c.getGpArg(0));
call->setArgument(1, locals_.indirection_cia);
c.ret();
}
@@ -936,16 +947,27 @@ int X64Emitter::GenerateIndirectionBranch(uint32_t cia, GpVar& target,
// Spill registers. We could probably share this.
SpillRegisters();
// Issue the full indirection branch.
// Grab the target of the indirection.
// TODO(benvanik): remove once fixed: https://code.google.com/p/asmjit/issues/detail?id=86
GpVar arg2 = c.newGpVar(kX86VarTypeGpq);
c.mov(arg2, imm(cia));
X86CompilerFuncCall* call = c.call(global_exports_.XeIndirectBranch);
call->setPrototype(kX86FuncConvDefault,
FuncBuilder3<void, void*, uint64_t, uint64_t>());
FuncBuilder3<void*, void*, uint64_t, uint64_t>());
call->setArgument(0, c.getGpArg(0));
call->setArgument(1, target);
call->setArgument(2, arg2);
GpVar target_ptr(c.newGpVar());
call->setReturn(target_ptr);
// Call target.
// void fn(ppc_state*, uint64_t)
call = c.call(target_ptr);
call->setComment("Indirection branch");
call->setPrototype(kX86FuncConvDefault,
FuncBuilder2<void, void*, uint64_t>());
call->setArgument(0, c.getGpArg(0));
call->setArgument(1, arg2);
// TODO(benvanik): next_block/is_last_block/etc
//if (next_block) {

View File

@@ -138,23 +138,32 @@ int X64JIT::UninitModule(ExecModule* module) {
return 0;
}
int X64JIT::Execute(xe_ppc_state_t* ppc_state, FunctionSymbol* fn_symbol) {
XELOGCPU("Execute(%.8X): %s...", fn_symbol->start_address, fn_symbol->name());
void* X64JIT::GetFunctionPointer(sdb::FunctionSymbol* fn_symbol) {
// Check function.
x64_function_t fn_ptr = (x64_function_t)fn_symbol->impl_value;
if (!fn_ptr) {
// Function hasn't been prepped yet - make it now inline.
// The emitter will lock and do other fancy things, if required.
if (emitter_->PrepareFunction(fn_symbol)) {
XELOGCPU("Execute(%.8X): unable to make function %s",
fn_symbol->start_address, fn_symbol->name());
return 1;
return NULL;
}
fn_ptr = (x64_function_t)fn_symbol->impl_value;
XEASSERTNOTNULL(fn_ptr);
}
return fn_ptr;
}
int X64JIT::Execute(xe_ppc_state_t* ppc_state, FunctionSymbol* fn_symbol) {
XELOGCPU("Execute(%.8X): %s...", fn_symbol->start_address, fn_symbol->name());
x64_function_t fn_ptr = (x64_function_t)GetFunctionPointer(fn_symbol);
if (!fn_ptr) {
XELOGCPU("Execute(%.8X): unable to make function %s",
fn_symbol->start_address, fn_symbol->name());
return 1;
}
// Call into the function. This will compile it if needed.
fn_ptr(ppc_state, ppc_state->lr);

View File

@@ -33,6 +33,7 @@ public:
virtual int InitModule(ExecModule* module);
virtual int UninitModule(ExecModule* module);
virtual void* GetFunctionPointer(sdb::FunctionSymbol* fn_symbol);
virtual int Execute(xe_ppc_state_t* ppc_state,
sdb::FunctionSymbol* fn_symbol);