parent
2a65442933
commit
3432a08e0a
5 changed files with 59 additions and 1 deletions
|
@ -22,6 +22,7 @@
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/bit_util.h"
|
#include "common/bit_util.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
#include "common/scope_exit.h"
|
||||||
#include "common/variant_util.h"
|
#include "common/variant_util.h"
|
||||||
#include "frontend/A32/location_descriptor.h"
|
#include "frontend/A32/location_descriptor.h"
|
||||||
#include "frontend/A32/types.h"
|
#include "frontend/A32/types.h"
|
||||||
|
@ -85,6 +86,9 @@ A32EmitX64::A32EmitX64(BlockOfCode& code, A32::UserConfig config, A32::Jit* jit_
|
||||||
A32EmitX64::~A32EmitX64() = default;
|
A32EmitX64::~A32EmitX64() = default;
|
||||||
|
|
||||||
A32EmitX64::BlockDescriptor A32EmitX64::Emit(IR::Block& block) {
|
A32EmitX64::BlockDescriptor A32EmitX64::Emit(IR::Block& block) {
|
||||||
|
code.EnableWriting();
|
||||||
|
SCOPE_EXIT { code.DisableWriting(); };
|
||||||
|
|
||||||
code.align();
|
code.align();
|
||||||
const u8* const entrypoint = code.getCurr();
|
const u8* const entrypoint = code.getCurr();
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/bit_util.h"
|
#include "common/bit_util.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
#include "common/scope_exit.h"
|
||||||
#include "common/variant_util.h"
|
#include "common/variant_util.h"
|
||||||
#include "frontend/A64/location_descriptor.h"
|
#include "frontend/A64/location_descriptor.h"
|
||||||
#include "frontend/A64/types.h"
|
#include "frontend/A64/types.h"
|
||||||
|
@ -71,6 +72,9 @@ A64EmitX64::A64EmitX64(BlockOfCode& code, A64::UserConfig conf, A64::Jit* jit_in
|
||||||
A64EmitX64::~A64EmitX64() = default;
|
A64EmitX64::~A64EmitX64() = default;
|
||||||
|
|
||||||
A64EmitX64::BlockDescriptor A64EmitX64::Emit(IR::Block& block) {
|
A64EmitX64::BlockDescriptor A64EmitX64::Emit(IR::Block& block) {
|
||||||
|
code.EnableWriting();
|
||||||
|
SCOPE_EXIT { code.DisableWriting(); };
|
||||||
|
|
||||||
code.align();
|
code.align();
|
||||||
const u8* const entrypoint = code.getCurr();
|
const u8* const entrypoint = code.getCurr();
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,12 @@
|
||||||
#include "backend/x64/block_of_code.h"
|
#include "backend/x64/block_of_code.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Dynarmic::BackendX64 {
|
namespace Dynarmic::BackendX64 {
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -36,16 +42,42 @@ const Xbyak::Reg64 BlockOfCode::ABI_PARAM6 = Xbyak::util::r9;
|
||||||
const std::array<Xbyak::Reg64, 6> BlockOfCode::ABI_PARAMS = {BlockOfCode::ABI_PARAM1, BlockOfCode::ABI_PARAM2, BlockOfCode::ABI_PARAM3, BlockOfCode::ABI_PARAM4, BlockOfCode::ABI_PARAM5, BlockOfCode::ABI_PARAM6};
|
const std::array<Xbyak::Reg64, 6> BlockOfCode::ABI_PARAMS = {BlockOfCode::ABI_PARAM1, BlockOfCode::ABI_PARAM2, BlockOfCode::ABI_PARAM3, BlockOfCode::ABI_PARAM4, BlockOfCode::ABI_PARAM5, BlockOfCode::ABI_PARAM6};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
constexpr size_t TOTAL_CODE_SIZE = 128 * 1024 * 1024;
|
constexpr size_t TOTAL_CODE_SIZE = 128 * 1024 * 1024;
|
||||||
constexpr size_t FAR_CODE_OFFSET = 100 * 1024 * 1024;
|
constexpr size_t FAR_CODE_OFFSET = 100 * 1024 * 1024;
|
||||||
constexpr size_t CONSTANT_POOL_SIZE = 2 * 1024 * 1024;
|
constexpr size_t CONSTANT_POOL_SIZE = 2 * 1024 * 1024;
|
||||||
|
|
||||||
|
class CustomXbyakAllocator : public Xbyak::Allocator {
|
||||||
|
public:
|
||||||
|
bool useProtect() const override { return false; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is threadsafe as Xbyak::Allocator does not contain any state; it is a pure interface.
|
||||||
|
CustomXbyakAllocator s_allocator;
|
||||||
|
|
||||||
|
void ProtectMemory(const void* base, size_t size, bool is_executable) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
DWORD oldProtect = 0;
|
||||||
|
VirtualProtect(const_cast<void*>(base), size, is_executable ? PAGE_EXECUTE_READ : PAGE_READWRITE, &oldProtect);
|
||||||
|
#else
|
||||||
|
static const size_t pageSize = sysconf(_SC_PAGESIZE);
|
||||||
|
const size_t iaddr = reinterpret_cast<size_t>(base);
|
||||||
|
const size_t roundAddr = iaddr & ~(pageSize - static_cast<size_t>(1));
|
||||||
|
const int mode = is_executable ? (PROT_READ | PROT_EXEC) : (PROT_READ | PROT_WRITE);
|
||||||
|
mprotect(reinterpret_cast<void*>(roundAddr), size + (iaddr - roundAddr), mode);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
BlockOfCode::BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi)
|
BlockOfCode::BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi)
|
||||||
: Xbyak::CodeGenerator(TOTAL_CODE_SIZE)
|
: 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();
|
||||||
GenRunCode();
|
GenRunCode();
|
||||||
exception_handler.Register(*this);
|
exception_handler.Register(*this);
|
||||||
}
|
}
|
||||||
|
@ -55,6 +87,15 @@ void BlockOfCode::PreludeComplete() {
|
||||||
near_code_begin = getCurr();
|
near_code_begin = getCurr();
|
||||||
far_code_begin = getCurr() + FAR_CODE_OFFSET;
|
far_code_begin = getCurr() + FAR_CODE_OFFSET;
|
||||||
ClearCache();
|
ClearCache();
|
||||||
|
DisableWriting();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlockOfCode::EnableWriting() {
|
||||||
|
ProtectMemory(getCode(), maxSize_, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlockOfCode::DisableWriting() {
|
||||||
|
ProtectMemory(getCode(), maxSize_, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockOfCode::ClearCache() {
|
void BlockOfCode::ClearCache() {
|
||||||
|
|
|
@ -34,6 +34,11 @@ public:
|
||||||
/// Call when external emitters have finished emitting their preludes.
|
/// Call when external emitters have finished emitting their preludes.
|
||||||
void PreludeComplete();
|
void PreludeComplete();
|
||||||
|
|
||||||
|
/// Change permissions to RW. This is required to support systems with W^X enforced.
|
||||||
|
void EnableWriting();
|
||||||
|
/// Change permissions to RX. This is required to support systems with W^X enforced.
|
||||||
|
void DisableWriting();
|
||||||
|
|
||||||
/// 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. This is the minimum of near code and far code.
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/bit_util.h"
|
#include "common/bit_util.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
#include "common/scope_exit.h"
|
||||||
#include "common/variant_util.h"
|
#include "common/variant_util.h"
|
||||||
#include "frontend/ir/basic_block.h"
|
#include "frontend/ir/basic_block.h"
|
||||||
#include "frontend/ir/microinstruction.h"
|
#include "frontend/ir/microinstruction.h"
|
||||||
|
@ -327,6 +328,9 @@ void EmitX64::ClearCache() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::InvalidateBasicBlocks(const std::unordered_set<IR::LocationDescriptor>& locations) {
|
void EmitX64::InvalidateBasicBlocks(const std::unordered_set<IR::LocationDescriptor>& locations) {
|
||||||
|
code.EnableWriting();
|
||||||
|
SCOPE_EXIT { code.DisableWriting(); };
|
||||||
|
|
||||||
for (const auto &descriptor : locations) {
|
for (const auto &descriptor : locations) {
|
||||||
auto it = block_descriptors.find(descriptor);
|
auto it = block_descriptors.find(descriptor);
|
||||||
if (it == block_descriptors.end()) {
|
if (it == block_descriptors.end()) {
|
||||||
|
|
Loading…
Reference in a new issue