block_of_code: Remove far code machinery
This commit is contained in:
parent
dd60f4b7d8
commit
840982be95
10 changed files with 16 additions and 69 deletions
|
@ -114,9 +114,6 @@ A32EmitX64::BlockDescriptor A32EmitX64::Emit(IR::Block& block) {
|
||||||
// Start emitting.
|
// Start emitting.
|
||||||
code.align();
|
code.align();
|
||||||
const u8* const entrypoint = code.getCurr();
|
const u8* const entrypoint = code.getCurr();
|
||||||
code.SwitchToFarCode();
|
|
||||||
const u8* const entrypoint_far = code.getCurr();
|
|
||||||
code.SwitchToNearCode();
|
|
||||||
|
|
||||||
EmitCondPrelude(ctx);
|
EmitCondPrelude(ctx);
|
||||||
|
|
||||||
|
@ -168,7 +165,7 @@ A32EmitX64::BlockDescriptor A32EmitX64::Emit(IR::Block& block) {
|
||||||
const auto range = boost::icl::discrete_interval<u32>::closed(descriptor.PC(), end_location.PC() - 1);
|
const auto range = boost::icl::discrete_interval<u32>::closed(descriptor.PC(), end_location.PC() - 1);
|
||||||
block_ranges.AddRange(range, descriptor);
|
block_ranges.AddRange(range, descriptor);
|
||||||
|
|
||||||
return RegisterBlock(descriptor, entrypoint, entrypoint_far, size);
|
return RegisterBlock(descriptor, entrypoint, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void A32EmitX64::ClearCache() {
|
void A32EmitX64::ClearCache() {
|
||||||
|
|
|
@ -60,7 +60,7 @@ static Optimization::PolyfillOptions GenPolyfillOptions(const BlockOfCode& code)
|
||||||
|
|
||||||
struct Jit::Impl {
|
struct Jit::Impl {
|
||||||
Impl(Jit* jit, A32::UserConfig conf)
|
Impl(Jit* jit, A32::UserConfig conf)
|
||||||
: block_of_code(GenRunCodeCallbacks(conf.callbacks, &GetCurrentBlockThunk, this, conf), JitStateInfo{jit_state}, conf.code_cache_size, conf.far_code_offset, GenRCP(conf))
|
: block_of_code(GenRunCodeCallbacks(conf.callbacks, &GetCurrentBlockThunk, this, conf), JitStateInfo{jit_state}, conf.code_cache_size, GenRCP(conf))
|
||||||
, emitter(block_of_code, conf, jit)
|
, emitter(block_of_code, conf, jit)
|
||||||
, polyfill_options(GenPolyfillOptions(block_of_code))
|
, polyfill_options(GenPolyfillOptions(block_of_code))
|
||||||
, conf(std::move(conf))
|
, conf(std::move(conf))
|
||||||
|
|
|
@ -85,9 +85,6 @@ A64EmitX64::BlockDescriptor A64EmitX64::Emit(IR::Block& block) {
|
||||||
// Start emitting.
|
// Start emitting.
|
||||||
code.align();
|
code.align();
|
||||||
const u8* const entrypoint = code.getCurr();
|
const u8* const entrypoint = code.getCurr();
|
||||||
code.SwitchToFarCode();
|
|
||||||
const u8* const entrypoint_far = code.getCurr();
|
|
||||||
code.SwitchToNearCode();
|
|
||||||
|
|
||||||
ASSERT(block.GetCondition() == IR::Cond::AL);
|
ASSERT(block.GetCondition() == IR::Cond::AL);
|
||||||
|
|
||||||
|
@ -139,7 +136,7 @@ A64EmitX64::BlockDescriptor A64EmitX64::Emit(IR::Block& block) {
|
||||||
const auto range = boost::icl::discrete_interval<u64>::closed(descriptor.PC(), end_location.PC() - 1);
|
const auto range = boost::icl::discrete_interval<u64>::closed(descriptor.PC(), end_location.PC() - 1);
|
||||||
block_ranges.AddRange(range, descriptor);
|
block_ranges.AddRange(range, descriptor);
|
||||||
|
|
||||||
return RegisterBlock(descriptor, entrypoint, entrypoint_far, size);
|
return RegisterBlock(descriptor, entrypoint, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void A64EmitX64::ClearCache() {
|
void A64EmitX64::ClearCache() {
|
||||||
|
|
|
@ -58,7 +58,7 @@ 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, conf), JitStateInfo{jit_state}, conf.code_cache_size, conf.far_code_offset, GenRCP(conf))
|
, block_of_code(GenRunCodeCallbacks(conf.callbacks, &GetCurrentBlockThunk, this, conf), JitStateInfo{jit_state}, conf.code_cache_size, GenRCP(conf))
|
||||||
, emitter(block_of_code, conf, jit)
|
, emitter(block_of_code, conf, jit)
|
||||||
, polyfill_options(GenPolyfillOptions(block_of_code)) {
|
, polyfill_options(GenPolyfillOptions(block_of_code)) {
|
||||||
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);
|
||||||
|
|
|
@ -185,22 +185,19 @@ HostFeature GetHostFeatures() {
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
BlockOfCode::BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi, size_t total_code_size, size_t far_code_offset, std::function<void(BlockOfCode&)> rcp)
|
BlockOfCode::BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi, size_t total_code_size, 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)
|
||||||
, far_code_offset(far_code_offset)
|
|
||||||
, constant_pool(*this, CONSTANT_POOL_SIZE)
|
, constant_pool(*this, CONSTANT_POOL_SIZE)
|
||||||
, host_features(GetHostFeatures()) {
|
, host_features(GetHostFeatures()) {
|
||||||
ASSERT(total_code_size > far_code_offset);
|
|
||||||
EnableWriting();
|
EnableWriting();
|
||||||
GenRunCode(rcp);
|
GenRunCode(rcp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockOfCode::PreludeComplete() {
|
void BlockOfCode::PreludeComplete() {
|
||||||
prelude_complete = true;
|
prelude_complete = true;
|
||||||
near_code_begin = getCurr();
|
code_begin = getCurr();
|
||||||
far_code_begin = getCurr() + far_code_offset;
|
|
||||||
ClearCache();
|
ClearCache();
|
||||||
DisableWriting();
|
DisableWriting();
|
||||||
}
|
}
|
||||||
|
@ -219,21 +216,15 @@ void BlockOfCode::DisableWriting() {
|
||||||
|
|
||||||
void BlockOfCode::ClearCache() {
|
void BlockOfCode::ClearCache() {
|
||||||
ASSERT(prelude_complete);
|
ASSERT(prelude_complete);
|
||||||
in_far_code = false;
|
SetCodePtr(code_begin);
|
||||||
near_code_ptr = near_code_begin;
|
|
||||||
far_code_ptr = far_code_begin;
|
|
||||||
SetCodePtr(near_code_begin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t BlockOfCode::SpaceRemaining() const {
|
size_t BlockOfCode::SpaceRemaining() const {
|
||||||
ASSERT(prelude_complete);
|
ASSERT(prelude_complete);
|
||||||
const u8* current_near_ptr = in_far_code ? reinterpret_cast<const u8*>(near_code_ptr) : getCurr<const u8*>();
|
const u8* current_ptr = getCurr<const u8*>();
|
||||||
const u8* current_far_ptr = in_far_code ? getCurr<const u8*>() : reinterpret_cast<const u8*>(far_code_ptr);
|
if (current_ptr >= &top_[maxSize_])
|
||||||
if (current_near_ptr >= far_code_begin)
|
|
||||||
return 0;
|
return 0;
|
||||||
if (current_far_ptr >= &top_[maxSize_])
|
return &top_[maxSize_] - current_ptr;
|
||||||
return 0;
|
|
||||||
return std::min(reinterpret_cast<const u8*>(far_code_begin) - current_near_ptr, &top_[maxSize_] - current_far_ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HaltReason BlockOfCode::RunCode(void* jit_state, CodePtr code_ptr) const {
|
HaltReason BlockOfCode::RunCode(void* jit_state, CodePtr code_ptr) const {
|
||||||
|
@ -406,26 +397,8 @@ Xbyak::Address BlockOfCode::XmmConst(const Xbyak::AddressFrame& frame, u64 lower
|
||||||
return constant_pool.GetConstant(frame, lower, upper);
|
return constant_pool.GetConstant(frame, lower, upper);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockOfCode::SwitchToFarCode() {
|
|
||||||
ASSERT(prelude_complete);
|
|
||||||
ASSERT(!in_far_code);
|
|
||||||
in_far_code = true;
|
|
||||||
near_code_ptr = getCurr();
|
|
||||||
SetCodePtr(far_code_ptr);
|
|
||||||
|
|
||||||
ASSERT_MSG(near_code_ptr < far_code_begin, "Near code has overwritten far code!");
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlockOfCode::SwitchToNearCode() {
|
|
||||||
ASSERT(prelude_complete);
|
|
||||||
ASSERT(in_far_code);
|
|
||||||
in_far_code = false;
|
|
||||||
far_code_ptr = getCurr();
|
|
||||||
SetCodePtr(near_code_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
CodePtr BlockOfCode::GetCodeBegin() const {
|
CodePtr BlockOfCode::GetCodeBegin() const {
|
||||||
return near_code_begin;
|
return code_begin;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t BlockOfCode::GetTotalCodeSize() const {
|
size_t BlockOfCode::GetTotalCodeSize() const {
|
||||||
|
|
|
@ -36,7 +36,7 @@ struct RunCodeCallbacks {
|
||||||
|
|
||||||
class BlockOfCode final : public Xbyak::CodeGenerator {
|
class BlockOfCode final : public Xbyak::CodeGenerator {
|
||||||
public:
|
public:
|
||||||
BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi, size_t total_code_size, size_t far_code_offset, std::function<void(BlockOfCode&)> rcp);
|
BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi, size_t total_code_size, 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.
|
||||||
|
@ -49,7 +49,7 @@ public:
|
||||||
|
|
||||||
/// 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();
|
||||||
/// Calculates how much space is remaining to use. This is the minimum of near code and far code.
|
/// Calculates how much space is remaining to use.
|
||||||
size_t SpaceRemaining() const;
|
size_t SpaceRemaining() const;
|
||||||
|
|
||||||
/// Runs emulated code from code_ptr.
|
/// Runs emulated code from code_ptr.
|
||||||
|
@ -125,11 +125,6 @@ public:
|
||||||
mcl::bit::replicate_element<u64>(esize, value));
|
mcl::bit::replicate_element<u64>(esize, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Far code sits far away from the near code. Execution remains primarily in near code.
|
|
||||||
/// "Cold" / Rarely executed instructions sit in far code, so the CPU doesn't fetch them unless necessary.
|
|
||||||
void SwitchToFarCode();
|
|
||||||
void SwitchToNearCode();
|
|
||||||
|
|
||||||
CodePtr GetCodeBegin() const;
|
CodePtr GetCodeBegin() const;
|
||||||
size_t GetTotalCodeSize() const;
|
size_t GetTotalCodeSize() const;
|
||||||
|
|
||||||
|
@ -180,18 +175,12 @@ public:
|
||||||
private:
|
private:
|
||||||
RunCodeCallbacks cb;
|
RunCodeCallbacks cb;
|
||||||
JitStateInfo jsi;
|
JitStateInfo jsi;
|
||||||
size_t far_code_offset;
|
|
||||||
|
|
||||||
bool prelude_complete = false;
|
bool prelude_complete = false;
|
||||||
CodePtr near_code_begin = nullptr;
|
CodePtr code_begin = nullptr;
|
||||||
CodePtr far_code_begin = nullptr;
|
|
||||||
|
|
||||||
ConstantPool constant_pool;
|
ConstantPool constant_pool;
|
||||||
|
|
||||||
bool in_far_code = false;
|
|
||||||
CodePtr near_code_ptr;
|
|
||||||
CodePtr far_code_ptr;
|
|
||||||
|
|
||||||
using RunCodeFuncType = HaltReason (*)(void*, CodePtr);
|
using RunCodeFuncType = HaltReason (*)(void*, CodePtr);
|
||||||
RunCodeFuncType run_code = nullptr;
|
RunCodeFuncType run_code = nullptr;
|
||||||
RunCodeFuncType step_code = nullptr;
|
RunCodeFuncType step_code = nullptr;
|
||||||
|
|
|
@ -276,11 +276,8 @@ Xbyak::Label EmitX64::EmitCond(IR::Cond cond) {
|
||||||
return pass;
|
return pass;
|
||||||
}
|
}
|
||||||
|
|
||||||
EmitX64::BlockDescriptor EmitX64::RegisterBlock(const IR::LocationDescriptor& descriptor, CodePtr entrypoint, CodePtr entrypoint_far, size_t size) {
|
EmitX64::BlockDescriptor EmitX64::RegisterBlock(const IR::LocationDescriptor& descriptor, CodePtr entrypoint, size_t size) {
|
||||||
PerfMapRegister(entrypoint, code.getCurr(), LocationDescriptorToFriendlyName(descriptor));
|
PerfMapRegister(entrypoint, code.getCurr(), LocationDescriptorToFriendlyName(descriptor));
|
||||||
code.SwitchToFarCode();
|
|
||||||
PerfMapRegister(entrypoint_far, code.getCurr(), LocationDescriptorToFriendlyName(descriptor) + "_far");
|
|
||||||
code.SwitchToNearCode();
|
|
||||||
Patch(descriptor, entrypoint);
|
Patch(descriptor, entrypoint);
|
||||||
|
|
||||||
BlockDescriptor block_desc{entrypoint, size};
|
BlockDescriptor block_desc{entrypoint, size};
|
||||||
|
|
|
@ -105,7 +105,7 @@ protected:
|
||||||
virtual std::string LocationDescriptorToFriendlyName(const IR::LocationDescriptor&) const = 0;
|
virtual std::string LocationDescriptorToFriendlyName(const IR::LocationDescriptor&) const = 0;
|
||||||
void EmitAddCycles(size_t cycles);
|
void EmitAddCycles(size_t cycles);
|
||||||
Xbyak::Label EmitCond(IR::Cond cond);
|
Xbyak::Label EmitCond(IR::Cond cond);
|
||||||
BlockDescriptor RegisterBlock(const IR::LocationDescriptor& location_descriptor, CodePtr entrypoint, CodePtr entrypoint_far, size_t size);
|
BlockDescriptor RegisterBlock(const IR::LocationDescriptor& location_descriptor, CodePtr entrypoint, size_t size);
|
||||||
void PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_reg, IR::LocationDescriptor target);
|
void PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_reg, IR::LocationDescriptor target);
|
||||||
|
|
||||||
// Terminal instruction emitters
|
// Terminal instruction emitters
|
||||||
|
|
|
@ -229,9 +229,6 @@ struct UserConfig {
|
||||||
// Minimum size is about 8MiB. Maximum size is about 2GiB. Maximum size is limited by
|
// Minimum size is about 8MiB. Maximum size is about 2GiB. Maximum size is limited by
|
||||||
// the maximum length of a x64 jump.
|
// the maximum length of a x64 jump.
|
||||||
size_t code_cache_size = 256 * 1024 * 1024; // bytes
|
size_t code_cache_size = 256 * 1024 * 1024; // bytes
|
||||||
// Determines the relative size of the near and far code caches. Must be smaller than
|
|
||||||
// code_cache_size.
|
|
||||||
size_t far_code_offset = 200 * 1024 * 1024; // bytes
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace A32
|
} // namespace A32
|
||||||
|
|
|
@ -288,9 +288,6 @@ struct UserConfig {
|
||||||
// Minimum size is about 8MiB. Maximum size is about 2GiB. Maximum size is limited by
|
// Minimum size is about 8MiB. Maximum size is about 2GiB. Maximum size is limited by
|
||||||
// the maximum length of a x64 jump.
|
// the maximum length of a x64 jump.
|
||||||
size_t code_cache_size = 256 * 1024 * 1024; // bytes
|
size_t code_cache_size = 256 * 1024 * 1024; // bytes
|
||||||
// Determines the relative size of the near and far code caches. Must be smaller than
|
|
||||||
// code_cache_size.
|
|
||||||
size_t far_code_offset = 200 * 1024 * 1024; // bytes
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace A64
|
} // namespace A64
|
||||||
|
|
Loading…
Reference in a new issue