a32_emit_x64: Use r14 for page_table pointer
This commit is contained in:
parent
49fcfe040c
commit
ad52c997f4
5 changed files with 47 additions and 17 deletions
|
@ -4,6 +4,7 @@
|
||||||
* General Public License version 2 or any later version.
|
* General Public License version 2 or any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
@ -85,7 +86,15 @@ A32EmitX64::BlockDescriptor A32EmitX64::Emit(IR::Block& block) {
|
||||||
// Start emitting.
|
// Start emitting.
|
||||||
EmitCondPrelude(block);
|
EmitCondPrelude(block);
|
||||||
|
|
||||||
RegAlloc reg_alloc{code, A32JitState::SpillCount, SpillToOpArg<A32JitState>, any_gpr, any_xmm};
|
static const std::vector<HostLoc> gpr_order = [this]{
|
||||||
|
std::vector<HostLoc> gprs{any_gpr};
|
||||||
|
if (config.page_table) {
|
||||||
|
gprs.erase(std::find(gprs.begin(), gprs.end(), HostLoc::R14));
|
||||||
|
}
|
||||||
|
return gprs;
|
||||||
|
}();
|
||||||
|
|
||||||
|
RegAlloc reg_alloc{code, A32JitState::SpillCount, SpillToOpArg<A32JitState>, gpr_order, any_xmm};
|
||||||
A32EmitContext ctx{reg_alloc, block};
|
A32EmitContext ctx{reg_alloc, block};
|
||||||
|
|
||||||
for (auto iter = block.begin(); iter != block.end(); ++iter) {
|
for (auto iter = block.begin(); iter != block.end(); ++iter) {
|
||||||
|
@ -778,21 +787,20 @@ static Xbyak::RegExp EmitVAddrLookup(BlockOfCode& code, RegAlloc& reg_alloc,
|
||||||
Xbyak::Reg64 vaddr,
|
Xbyak::Reg64 vaddr,
|
||||||
std::optional<Xbyak::Reg64> arg_scratch = {}) {
|
std::optional<Xbyak::Reg64> arg_scratch = {}) {
|
||||||
constexpr size_t page_bits = A32::UserConfig::PAGE_BITS;
|
constexpr size_t page_bits = A32::UserConfig::PAGE_BITS;
|
||||||
const Xbyak::Reg64 page_table = arg_scratch ? *arg_scratch : reg_alloc.ScratchGpr();
|
const Xbyak::Reg64 page = arg_scratch ? *arg_scratch : reg_alloc.ScratchGpr();
|
||||||
const Xbyak::Reg64 tmp = reg_alloc.ScratchGpr();
|
const Xbyak::Reg64 tmp = config.absolute_offset_page_table ? page : reg_alloc.ScratchGpr();
|
||||||
code.mov(page_table, reinterpret_cast<u64>(config.page_table));
|
|
||||||
code.mov(tmp, vaddr);
|
code.mov(tmp, vaddr);
|
||||||
code.shr(tmp, static_cast<int>(page_bits));
|
code.shr(tmp, static_cast<int>(page_bits));
|
||||||
code.mov(page_table, qword[page_table + tmp * sizeof(void*)]);
|
code.mov(page, qword[r14 + tmp * sizeof(void*)]);
|
||||||
code.test(page_table, page_table);
|
code.test(page, page);
|
||||||
code.jz(abort);
|
code.jz(abort);
|
||||||
if (config.absolute_offset_page_table) {
|
if (config.absolute_offset_page_table) {
|
||||||
return page_table + vaddr;
|
return page + vaddr;
|
||||||
}
|
}
|
||||||
constexpr size_t page_mask = (1 << page_bits) - 1;
|
constexpr size_t page_mask = (1 << page_bits) - 1;
|
||||||
code.mov(tmp, vaddr);
|
code.mov(tmp, vaddr);
|
||||||
code.and_(tmp, static_cast<u32>(page_mask));
|
code.and_(tmp, static_cast<u32>(page_mask));
|
||||||
return page_table + tmp;
|
return page + tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<std::size_t bitsize>
|
template<std::size_t bitsize>
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* General Public License version 2 or any later version.
|
* General Public License version 2 or any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include <boost/icl/interval_set.hpp>
|
#include <boost/icl/interval_set.hpp>
|
||||||
|
@ -19,6 +20,7 @@
|
||||||
#include "backend/x64/devirtualize.h"
|
#include "backend/x64/devirtualize.h"
|
||||||
#include "backend/x64/jitstate_info.h"
|
#include "backend/x64/jitstate_info.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
#include "common/cast_util.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/llvm_disassemble.h"
|
#include "common/llvm_disassemble.h"
|
||||||
#include "common/scope_exit.h"
|
#include "common/scope_exit.h"
|
||||||
|
@ -39,9 +41,20 @@ static RunCodeCallbacks GenRunCodeCallbacks(A32::UserCallbacks* cb, CodePtr (*Lo
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::function<void(BlockOfCode&)> GenRCP(const A32::UserConfig& config) {
|
||||||
|
if (!config.page_table) {
|
||||||
|
return [](BlockOfCode&){};
|
||||||
|
}
|
||||||
|
|
||||||
|
const u64 r14_value = Common::BitCast<u64>(config.page_table);
|
||||||
|
return [r14_value](BlockOfCode& code) {
|
||||||
|
code.mov(code.r14, r14_value);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
struct Jit::Impl {
|
struct Jit::Impl {
|
||||||
Impl(Jit* jit, A32::UserConfig config)
|
Impl(Jit* jit, A32::UserConfig config)
|
||||||
: block_of_code(GenRunCodeCallbacks(config.callbacks, &GetCurrentBlockThunk, this), JitStateInfo{jit_state})
|
: block_of_code(GenRunCodeCallbacks(config.callbacks, &GetCurrentBlockThunk, this), JitStateInfo{jit_state}, GenRCP(config))
|
||||||
, emitter(block_of_code, config, jit)
|
, emitter(block_of_code, config, jit)
|
||||||
, config(std::move(config))
|
, config(std::move(config))
|
||||||
, jit_interface(jit)
|
, jit_interface(jit)
|
||||||
|
|
|
@ -34,11 +34,15 @@ static RunCodeCallbacks GenRunCodeCallbacks(A64::UserCallbacks* cb, CodePtr (*Lo
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::function<void(BlockOfCode&)> GenRCP(const A64::UserConfig&) {
|
||||||
|
return [](BlockOfCode&){};
|
||||||
|
}
|
||||||
|
|
||||||
struct Jit::Impl final {
|
struct Jit::Impl final {
|
||||||
public:
|
public:
|
||||||
Impl(Jit* jit, UserConfig conf)
|
Impl(Jit* jit, UserConfig conf)
|
||||||
: conf(conf)
|
: conf(conf)
|
||||||
, block_of_code(GenRunCodeCallbacks(conf.callbacks, &GetCurrentBlockThunk, this), JitStateInfo{jit_state})
|
, block_of_code(GenRunCodeCallbacks(conf.callbacks, &GetCurrentBlockThunk, this), JitStateInfo{jit_state}, GenRCP(conf))
|
||||||
, emitter(block_of_code, conf, jit)
|
, emitter(block_of_code, conf, jit)
|
||||||
{
|
{
|
||||||
ASSERT(conf.page_table_address_space_bits >= 12 && conf.page_table_address_space_bits <= 64);
|
ASSERT(conf.page_table_address_space_bits >= 12 && conf.page_table_address_space_bits <= 64);
|
||||||
|
|
|
@ -75,14 +75,14 @@ void ProtectMemory(const void* base, size_t size, bool is_executable) {
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
BlockOfCode::BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi)
|
BlockOfCode::BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi, std::function<void(BlockOfCode&)> rcp)
|
||||||
: Xbyak::CodeGenerator(TOTAL_CODE_SIZE, nullptr, &s_allocator)
|
: Xbyak::CodeGenerator(TOTAL_CODE_SIZE, nullptr, &s_allocator)
|
||||||
, cb(std::move(cb))
|
, cb(std::move(cb))
|
||||||
, jsi(jsi)
|
, jsi(jsi)
|
||||||
, constant_pool(*this, CONSTANT_POOL_SIZE)
|
, constant_pool(*this, CONSTANT_POOL_SIZE)
|
||||||
{
|
{
|
||||||
EnableWriting();
|
EnableWriting();
|
||||||
GenRunCode();
|
GenRunCode(rcp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockOfCode::PreludeComplete() {
|
void BlockOfCode::PreludeComplete() {
|
||||||
|
@ -155,7 +155,7 @@ void BlockOfCode::ForceReturnFromRunCode(bool mxcsr_already_exited) {
|
||||||
jmp(return_from_run_code[index]);
|
jmp(return_from_run_code[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockOfCode::GenRunCode() {
|
void BlockOfCode::GenRunCode(std::function<void(BlockOfCode&)> rcp) {
|
||||||
Xbyak::Label loop, enter_mxcsr_then_loop;
|
Xbyak::Label loop, enter_mxcsr_then_loop;
|
||||||
|
|
||||||
align();
|
align();
|
||||||
|
@ -168,14 +168,16 @@ void BlockOfCode::GenRunCode() {
|
||||||
ABI_PushCalleeSaveRegistersAndAdjustStack(*this);
|
ABI_PushCalleeSaveRegistersAndAdjustStack(*this);
|
||||||
|
|
||||||
mov(r15, ABI_PARAM1);
|
mov(r15, ABI_PARAM1);
|
||||||
mov(r14, ABI_PARAM2); // save temporarily in non-volatile register
|
mov(rbx, ABI_PARAM2); // save temporarily in non-volatile register
|
||||||
|
|
||||||
cb.GetTicksRemaining->EmitCall(*this);
|
cb.GetTicksRemaining->EmitCall(*this);
|
||||||
mov(qword[r15 + jsi.offsetof_cycles_to_run], ABI_RETURN);
|
mov(qword[r15 + jsi.offsetof_cycles_to_run], ABI_RETURN);
|
||||||
mov(qword[r15 + jsi.offsetof_cycles_remaining], ABI_RETURN);
|
mov(qword[r15 + jsi.offsetof_cycles_remaining], ABI_RETURN);
|
||||||
|
|
||||||
|
rcp(*this);
|
||||||
|
|
||||||
SwitchMxcsrOnEntry();
|
SwitchMxcsrOnEntry();
|
||||||
jmp(r14);
|
jmp(rbx);
|
||||||
|
|
||||||
align();
|
align();
|
||||||
step_code = getCurr<RunCodeFuncType>();
|
step_code = getCurr<RunCodeFuncType>();
|
||||||
|
@ -187,6 +189,8 @@ void BlockOfCode::GenRunCode() {
|
||||||
mov(qword[r15 + jsi.offsetof_cycles_to_run], 1);
|
mov(qword[r15 + jsi.offsetof_cycles_to_run], 1);
|
||||||
mov(qword[r15 + jsi.offsetof_cycles_remaining], 1);
|
mov(qword[r15 + jsi.offsetof_cycles_remaining], 1);
|
||||||
|
|
||||||
|
rcp(*this);
|
||||||
|
|
||||||
SwitchMxcsrOnEntry();
|
SwitchMxcsrOnEntry();
|
||||||
jmp(ABI_PARAM2);
|
jmp(ABI_PARAM2);
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
@ -31,7 +32,7 @@ struct RunCodeCallbacks {
|
||||||
|
|
||||||
class BlockOfCode final : public Xbyak::CodeGenerator {
|
class BlockOfCode final : public Xbyak::CodeGenerator {
|
||||||
public:
|
public:
|
||||||
BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi);
|
BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi, std::function<void(BlockOfCode&)> rcp);
|
||||||
BlockOfCode(const BlockOfCode&) = delete;
|
BlockOfCode(const BlockOfCode&) = delete;
|
||||||
|
|
||||||
/// Call when external emitters have finished emitting their preludes.
|
/// Call when external emitters have finished emitting their preludes.
|
||||||
|
@ -162,7 +163,7 @@ private:
|
||||||
static constexpr size_t MXCSR_ALREADY_EXITED = 1 << 0;
|
static constexpr size_t MXCSR_ALREADY_EXITED = 1 << 0;
|
||||||
static constexpr size_t FORCE_RETURN = 1 << 1;
|
static constexpr size_t FORCE_RETURN = 1 << 1;
|
||||||
std::array<const void*, 4> return_from_run_code;
|
std::array<const void*, 4> return_from_run_code;
|
||||||
void GenRunCode();
|
void GenRunCode(std::function<void(BlockOfCode&)> rcp);
|
||||||
|
|
||||||
Xbyak::util::Cpu cpu_info;
|
Xbyak::util::Cpu cpu_info;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue