backend_x64: Simplify dispatcher

This commit is contained in:
MerryMage 2017-04-07 10:52:44 +01:00
parent 523ae542f4
commit 1b37420459
4 changed files with 90 additions and 31 deletions

View file

@ -18,9 +18,14 @@
namespace Dynarmic { namespace Dynarmic {
namespace BackendX64 { namespace BackendX64 {
BlockOfCode::BlockOfCode(UserCallbacks cb) : Xbyak::CodeGenerator(128 * 1024 * 1024), cb(cb), constant_pool(this, 256) { BlockOfCode::BlockOfCode(UserCallbacks cb, LookupBlockCallback lookup_block, void* lookup_block_arg)
: Xbyak::CodeGenerator(128 * 1024 * 1024)
, cb(cb)
, lookup_block(lookup_block)
, lookup_block_arg(lookup_block_arg)
, constant_pool(this, 256)
{
GenRunCode(); GenRunCode();
GenReturnFromRunCode();
GenMemoryAccessors(); GenMemoryAccessors();
unwind_handler.Register(this); unwind_handler.Register(this);
user_code_begin = getCurr<CodePtr>(); user_code_begin = getCurr<CodePtr>();
@ -30,20 +35,32 @@ void BlockOfCode::ClearCache() {
SetCodePtr(user_code_begin); SetCodePtr(user_code_begin);
} }
size_t BlockOfCode::RunCode(JitState* jit_state, CodePtr basic_block, size_t cycles_to_run) const { size_t BlockOfCode::RunCode(JitState* jit_state, size_t cycles_to_run) const {
constexpr size_t max_cycles_to_run = static_cast<size_t>(std::numeric_limits<decltype(jit_state->cycles_remaining)>::max()); constexpr size_t max_cycles_to_run = static_cast<size_t>(std::numeric_limits<decltype(jit_state->cycles_remaining)>::max());
ASSERT(cycles_to_run <= max_cycles_to_run); ASSERT(cycles_to_run <= max_cycles_to_run);
jit_state->cycles_remaining = cycles_to_run; jit_state->cycles_remaining = cycles_to_run;
run_code(jit_state, basic_block); run_code(jit_state);
return cycles_to_run - jit_state->cycles_remaining; // Return number of cycles actually run. return cycles_to_run - jit_state->cycles_remaining; // Return number of cycles actually run.
} }
void BlockOfCode::ReturnFromRunCode(bool MXCSR_switch) { void BlockOfCode::ReturnFromRunCode(bool MXCSR_switch) {
jmp(MXCSR_switch ? return_from_run_code : return_from_run_code_without_mxcsr_switch); size_t index = 0;
if (!MXCSR_switch)
index |= NO_SWITCH_MXCSR;
jmp(return_from_run_code[index]);
}
void BlockOfCode::ForceReturnFromRunCode(bool MXCSR_switch) {
size_t index = FORCE_RETURN;
if (!MXCSR_switch)
index |= NO_SWITCH_MXCSR;
jmp(return_from_run_code[index]);
} }
void BlockOfCode::GenRunCode() { void BlockOfCode::GenRunCode() {
Xbyak::Label loop;
align(); align();
run_code = getCurr<RunCodeFuncType>(); run_code = getCurr<RunCodeFuncType>();
@ -54,19 +71,44 @@ void BlockOfCode::GenRunCode() {
ABI_PushCalleeSaveRegistersAndAdjustStack(this); ABI_PushCalleeSaveRegistersAndAdjustStack(this);
mov(r15, ABI_PARAM1); mov(r15, ABI_PARAM1);
L(loop);
mov(ABI_PARAM1, u64(lookup_block_arg));
CallFunction(lookup_block);
SwitchMxcsrOnEntry(); SwitchMxcsrOnEntry();
jmp(ABI_PARAM2); jmp(ABI_RETURN);
}
void BlockOfCode::GenReturnFromRunCode() { // Return from run code variants
return_from_run_code = getCurr<const void*>(); const auto emit_return_from_run_code = [this, &loop](bool no_mxcsr_switch, bool force_return){
if (!no_mxcsr_switch) {
SwitchMxcsrOnExit();
}
SwitchMxcsrOnExit(); if (!force_return) {
cmp(qword[r15 + offsetof(JitState, cycles_remaining)], 0);
jg(loop);
}
return_from_run_code_without_mxcsr_switch = getCurr<const void*>(); ABI_PopCalleeSaveRegistersAndAdjustStack(this);
ret();
};
ABI_PopCalleeSaveRegistersAndAdjustStack(this); align();
ret(); return_from_run_code[0] = getCurr<const void*>();
emit_return_from_run_code(false, false);
align();
return_from_run_code[NO_SWITCH_MXCSR] = getCurr<const void*>();
emit_return_from_run_code(true, false);
align();
return_from_run_code[FORCE_RETURN] = getCurr<const void*>();
emit_return_from_run_code(false, true);
align();
return_from_run_code[NO_SWITCH_MXCSR | FORCE_RETURN] = getCurr<const void*>();
emit_return_from_run_code(true, true);
} }
void BlockOfCode::GenMemoryAccessors() { void BlockOfCode::GenMemoryAccessors() {

View file

@ -19,17 +19,21 @@
namespace Dynarmic { namespace Dynarmic {
namespace BackendX64 { namespace BackendX64 {
using LookupBlockCallback = CodePtr(*)(void*);
class BlockOfCode final : public Xbyak::CodeGenerator { class BlockOfCode final : public Xbyak::CodeGenerator {
public: public:
explicit BlockOfCode(UserCallbacks cb); BlockOfCode(UserCallbacks cb, LookupBlockCallback lookup_block, void* lookup_block_arg);
/// Clears this block of code and resets code pointer to beginning. /// Clears this block of code and resets code pointer to beginning.
void ClearCache(); void ClearCache();
/// Runs emulated code for approximately `cycles_to_run` cycles. /// Runs emulated code for approximately `cycles_to_run` cycles.
size_t RunCode(JitState* jit_state, CodePtr basic_block, size_t cycles_to_run) const; size_t RunCode(JitState* jit_state, size_t cycles_to_run) const;
/// Code emitter: Returns to host /// Code emitter: Returns to dispatcher
void ReturnFromRunCode(bool MXCSR_switch = true); void ReturnFromRunCode(bool MXCSR_switch = true);
/// Code emitter: Returns to dispatcher, forces return to host
void ForceReturnFromRunCode(bool MXCSR_switch = true);
/// Code emitter: Makes guest MXCSR the current MXCSR /// Code emitter: Makes guest MXCSR the current MXCSR
void SwitchMxcsrOnEntry(); void SwitchMxcsrOnEntry();
/// Code emitter: Makes saved host MXCSR the current MXCSR /// Code emitter: Makes saved host MXCSR the current MXCSR
@ -56,7 +60,11 @@ public:
Xbyak::Address MConst(u64 constant); Xbyak::Address MConst(u64 constant);
const void* GetReturnFromRunCodeAddress() const { const void* GetReturnFromRunCodeAddress() const {
return return_from_run_code; return return_from_run_code[0];
}
const void* GetForceReturnFromRunCodeAddress() const {
return return_from_run_code[FORCE_RETURN];
} }
const void* GetMemoryReadCallback(size_t bit_size) const { const void* GetMemoryReadCallback(size_t bit_size) const {
@ -116,18 +124,20 @@ public:
private: private:
UserCallbacks cb; UserCallbacks cb;
LookupBlockCallback lookup_block;
void* lookup_block_arg;
CodePtr user_code_begin; CodePtr user_code_begin;
ConstantPool constant_pool; ConstantPool constant_pool;
using RunCodeFuncType = void(*)(JitState*, CodePtr); using RunCodeFuncType = void(*)(JitState*);
RunCodeFuncType run_code = nullptr; RunCodeFuncType run_code = nullptr;
static constexpr size_t NO_SWITCH_MXCSR = 1 << 0;
static constexpr size_t FORCE_RETURN = 1 << 1;
std::array<const void*, 4> return_from_run_code;
void GenRunCode(); void GenRunCode();
const void* return_from_run_code = nullptr;
const void* return_from_run_code_without_mxcsr_switch = nullptr;
void GenReturnFromRunCode();
const void* read_memory_8 = nullptr; const void* read_memory_8 = nullptr;
const void* read_memory_16 = nullptr; const void* read_memory_16 = nullptr;
const void* read_memory_32 = nullptr; const void* read_memory_32 = nullptr;

View file

@ -3403,7 +3403,7 @@ void EmitX64::EmitTerminal(IR::Term::LinkBlock terminal, IR::LocationDescriptor
} }
code->mov(MJitStateReg(Arm::Reg::PC), terminal.next.PC()); code->mov(MJitStateReg(Arm::Reg::PC), terminal.next.PC());
code->ReturnFromRunCode(); // TODO: Check cycles, Properly do a link code->ForceReturnFromRunCode(); // TODO: Check cycles, Properly do a link
} }
void EmitX64::EmitTerminal(IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location) { void EmitX64::EmitTerminal(IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location) {
@ -3464,7 +3464,7 @@ void EmitX64::EmitTerminal(IR::Term::CheckHalt terminal, IR::LocationDescriptor
using namespace Xbyak::util; using namespace Xbyak::util;
code->cmp(code->byte[r15 + offsetof(JitState, halt_requested)], u8(0)); code->cmp(code->byte[r15 + offsetof(JitState, halt_requested)], u8(0));
code->jne(code->GetReturnFromRunCodeAddress()); code->jne(code->GetForceReturnFromRunCodeAddress());
EmitTerminal(terminal.else_, initial_location); EmitTerminal(terminal.else_, initial_location);
} }

View file

@ -32,7 +32,7 @@ using namespace BackendX64;
struct Jit::Impl { struct Jit::Impl {
Impl(Jit* jit, UserCallbacks callbacks) Impl(Jit* jit, UserCallbacks callbacks)
: block_of_code(callbacks) : block_of_code(callbacks, &GetCurrentBlock, this)
, jit_state() , jit_state()
, emitter(&block_of_code, callbacks, jit) , emitter(&block_of_code, callbacks, jit)
, callbacks(callbacks) , callbacks(callbacks)
@ -48,12 +48,7 @@ struct Jit::Impl {
std::queue<Common::AddressRange> invalid_cache_ranges; std::queue<Common::AddressRange> invalid_cache_ranges;
size_t Execute(size_t cycle_count) { size_t Execute(size_t cycle_count) {
u32 pc = jit_state.Reg[15]; return block_of_code.RunCode(&jit_state, cycle_count);
IR::LocationDescriptor descriptor{pc, Arm::PSR{jit_state.Cpsr}, Arm::FPSCR{jit_state.FPSCR_mode}};
CodePtr entrypoint = GetBasicBlock(descriptor).entrypoint;
return block_of_code.RunCode(&jit_state, entrypoint, cycle_count);
} }
std::string Disassemble(const IR::LocationDescriptor& descriptor) { std::string Disassemble(const IR::LocationDescriptor& descriptor) {
@ -119,6 +114,18 @@ struct Jit::Impl {
private: private:
Jit* jit_interface; Jit* jit_interface;
static CodePtr GetCurrentBlock(void *this_voidptr) {
Jit::Impl& this_ = *reinterpret_cast<Jit::Impl*>(this_voidptr);
JitState& jit_state = this_.jit_state;
u32 pc = jit_state.Reg[15];
Arm::PSR cpsr{jit_state.Cpsr};
Arm::FPSCR fpscr{jit_state.FPSCR_mode};
IR::LocationDescriptor descriptor{pc, cpsr, fpscr};
return this_.GetBasicBlock(descriptor).entrypoint;
}
EmitX64::BlockDescriptor GetBasicBlock(IR::LocationDescriptor descriptor) { EmitX64::BlockDescriptor GetBasicBlock(IR::LocationDescriptor descriptor) {
auto block = emitter.GetBasicBlock(descriptor); auto block = emitter.GetBasicBlock(descriptor);
if (block) if (block)