backend_x64: Simplify dispatcher
This commit is contained in:
parent
523ae542f4
commit
1b37420459
4 changed files with 90 additions and 31 deletions
|
@ -18,9 +18,14 @@
|
|||
namespace Dynarmic {
|
||||
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();
|
||||
GenReturnFromRunCode();
|
||||
GenMemoryAccessors();
|
||||
unwind_handler.Register(this);
|
||||
user_code_begin = getCurr<CodePtr>();
|
||||
|
@ -30,20 +35,32 @@ void BlockOfCode::ClearCache() {
|
|||
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());
|
||||
ASSERT(cycles_to_run <= max_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.
|
||||
}
|
||||
|
||||
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() {
|
||||
Xbyak::Label loop;
|
||||
|
||||
align();
|
||||
run_code = getCurr<RunCodeFuncType>();
|
||||
|
||||
|
@ -54,19 +71,44 @@ void BlockOfCode::GenRunCode() {
|
|||
ABI_PushCalleeSaveRegistersAndAdjustStack(this);
|
||||
|
||||
mov(r15, ABI_PARAM1);
|
||||
|
||||
L(loop);
|
||||
mov(ABI_PARAM1, u64(lookup_block_arg));
|
||||
CallFunction(lookup_block);
|
||||
|
||||
SwitchMxcsrOnEntry();
|
||||
jmp(ABI_PARAM2);
|
||||
}
|
||||
|
||||
void BlockOfCode::GenReturnFromRunCode() {
|
||||
return_from_run_code = getCurr<const void*>();
|
||||
jmp(ABI_RETURN);
|
||||
|
||||
// Return from run code variants
|
||||
const auto emit_return_from_run_code = [this, &loop](bool no_mxcsr_switch, bool force_return){
|
||||
if (!no_mxcsr_switch) {
|
||||
SwitchMxcsrOnExit();
|
||||
}
|
||||
|
||||
return_from_run_code_without_mxcsr_switch = getCurr<const void*>();
|
||||
if (!force_return) {
|
||||
cmp(qword[r15 + offsetof(JitState, cycles_remaining)], 0);
|
||||
jg(loop);
|
||||
}
|
||||
|
||||
ABI_PopCalleeSaveRegistersAndAdjustStack(this);
|
||||
ret();
|
||||
};
|
||||
|
||||
align();
|
||||
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() {
|
||||
|
|
|
@ -19,17 +19,21 @@
|
|||
namespace Dynarmic {
|
||||
namespace BackendX64 {
|
||||
|
||||
using LookupBlockCallback = CodePtr(*)(void*);
|
||||
|
||||
class BlockOfCode final : public Xbyak::CodeGenerator {
|
||||
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.
|
||||
void ClearCache();
|
||||
|
||||
/// Runs emulated code for approximately `cycles_to_run` cycles.
|
||||
size_t RunCode(JitState* jit_state, CodePtr basic_block, size_t cycles_to_run) const;
|
||||
/// Code emitter: Returns to host
|
||||
size_t RunCode(JitState* jit_state, size_t cycles_to_run) const;
|
||||
/// Code emitter: Returns to dispatcher
|
||||
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
|
||||
void SwitchMxcsrOnEntry();
|
||||
/// Code emitter: Makes saved host MXCSR the current MXCSR
|
||||
|
@ -56,7 +60,11 @@ public:
|
|||
Xbyak::Address MConst(u64 constant);
|
||||
|
||||
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 {
|
||||
|
@ -116,18 +124,20 @@ public:
|
|||
|
||||
private:
|
||||
UserCallbacks cb;
|
||||
LookupBlockCallback lookup_block;
|
||||
void* lookup_block_arg;
|
||||
|
||||
CodePtr user_code_begin;
|
||||
|
||||
ConstantPool constant_pool;
|
||||
|
||||
using RunCodeFuncType = void(*)(JitState*, CodePtr);
|
||||
using RunCodeFuncType = void(*)(JitState*);
|
||||
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();
|
||||
|
||||
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_16 = nullptr;
|
||||
const void* read_memory_32 = nullptr;
|
||||
|
|
|
@ -3403,7 +3403,7 @@ void EmitX64::EmitTerminal(IR::Term::LinkBlock terminal, IR::LocationDescriptor
|
|||
}
|
||||
|
||||
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) {
|
||||
|
@ -3464,7 +3464,7 @@ void EmitX64::EmitTerminal(IR::Term::CheckHalt terminal, IR::LocationDescriptor
|
|||
using namespace Xbyak::util;
|
||||
|
||||
code->cmp(code->byte[r15 + offsetof(JitState, halt_requested)], u8(0));
|
||||
code->jne(code->GetReturnFromRunCodeAddress());
|
||||
code->jne(code->GetForceReturnFromRunCodeAddress());
|
||||
EmitTerminal(terminal.else_, initial_location);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ using namespace BackendX64;
|
|||
|
||||
struct Jit::Impl {
|
||||
Impl(Jit* jit, UserCallbacks callbacks)
|
||||
: block_of_code(callbacks)
|
||||
: block_of_code(callbacks, &GetCurrentBlock, this)
|
||||
, jit_state()
|
||||
, emitter(&block_of_code, callbacks, jit)
|
||||
, callbacks(callbacks)
|
||||
|
@ -48,12 +48,7 @@ struct Jit::Impl {
|
|||
std::queue<Common::AddressRange> invalid_cache_ranges;
|
||||
|
||||
size_t Execute(size_t cycle_count) {
|
||||
u32 pc = jit_state.Reg[15];
|
||||
|
||||
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);
|
||||
return block_of_code.RunCode(&jit_state, cycle_count);
|
||||
}
|
||||
|
||||
std::string Disassemble(const IR::LocationDescriptor& descriptor) {
|
||||
|
@ -119,6 +114,18 @@ struct Jit::Impl {
|
|||
private:
|
||||
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) {
|
||||
auto block = emitter.GetBasicBlock(descriptor);
|
||||
if (block)
|
||||
|
|
Loading…
Reference in a new issue