[dynarmic] memory-inline JIT implementation w/o exposing specific interfaces
Signed-off-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
parent
d06fbb933e
commit
89f424e61f
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
|
|
@ -64,13 +64,11 @@ struct Jit::Impl final {
|
|||
}
|
||||
|
||||
void ClearCache() {
|
||||
std::unique_lock lock{invalidation_mutex};
|
||||
invalidate_entire_cache = true;
|
||||
HaltExecution(HaltReason::CacheInvalidation);
|
||||
}
|
||||
|
||||
void InvalidateCacheRange(std::uint32_t start_address, std::size_t length) {
|
||||
std::unique_lock lock{invalidation_mutex};
|
||||
invalid_cache_ranges.add(boost::icl::discrete_interval<u32>::closed(start_address, static_cast<u32>(start_address + length - 1)));
|
||||
HaltExecution(HaltReason::CacheInvalidation);
|
||||
}
|
||||
|
|
@ -132,8 +130,6 @@ struct Jit::Impl final {
|
|||
private:
|
||||
void PerformRequestedCacheInvalidation(HaltReason hr) {
|
||||
if (Has(hr, HaltReason::CacheInvalidation)) {
|
||||
std::unique_lock lock{invalidation_mutex};
|
||||
|
||||
ClearHalt(HaltReason::CacheInvalidation);
|
||||
|
||||
if (invalidate_entire_cache) {
|
||||
|
|
@ -160,83 +156,90 @@ private:
|
|||
A32Core core;
|
||||
|
||||
volatile u32 halt_reason = 0;
|
||||
|
||||
std::mutex invalidation_mutex;
|
||||
boost::icl::interval_set<u32> invalid_cache_ranges;
|
||||
bool invalidate_entire_cache = false;
|
||||
};
|
||||
static_assert(sizeof(Jit::Impl) <= sizeof(Jit::impl_storage));
|
||||
|
||||
Jit::Jit(UserConfig conf)
|
||||
: impl(std::make_unique<Impl>(this, conf)) {}
|
||||
|
||||
Jit::~Jit() = default;
|
||||
Jit::Jit(UserConfig conf) {
|
||||
new (&impl_storage[0]) Jit::Impl(this, conf);
|
||||
}
|
||||
Jit::~Jit() {
|
||||
reinterpret_cast<Jit::Impl*>(&impl_storage[0])->~Impl();
|
||||
}
|
||||
inline Jit::Impl* GetImpl(Jit& jit) noexcept {
|
||||
return reinterpret_cast<Jit::Impl*>(&jit.impl_storage[0]);
|
||||
}
|
||||
inline Jit::Impl const* GetImpl(Jit const& jit) noexcept {
|
||||
return reinterpret_cast<Jit::Impl const*>(&jit.impl_storage[0]);
|
||||
}
|
||||
|
||||
HaltReason Jit::Run() {
|
||||
return impl->Run();
|
||||
return GetImpl(*this)->Run();
|
||||
}
|
||||
|
||||
HaltReason Jit::Step() {
|
||||
return impl->Step();
|
||||
return GetImpl(*this)->Step();
|
||||
}
|
||||
|
||||
void Jit::ClearCache() {
|
||||
impl->ClearCache();
|
||||
GetImpl(*this)->ClearCache();
|
||||
}
|
||||
|
||||
void Jit::InvalidateCacheRange(std::uint32_t start_address, std::size_t length) {
|
||||
impl->InvalidateCacheRange(start_address, length);
|
||||
GetImpl(*this)->InvalidateCacheRange(start_address, length);
|
||||
}
|
||||
|
||||
void Jit::Reset() {
|
||||
impl->Reset();
|
||||
GetImpl(*this)->Reset();
|
||||
}
|
||||
|
||||
void Jit::HaltExecution(HaltReason hr) {
|
||||
impl->HaltExecution(hr);
|
||||
GetImpl(*this)->HaltExecution(hr);
|
||||
}
|
||||
|
||||
void Jit::ClearHalt(HaltReason hr) {
|
||||
impl->ClearHalt(hr);
|
||||
GetImpl(*this)->ClearHalt(hr);
|
||||
}
|
||||
|
||||
std::array<std::uint32_t, 16>& Jit::Regs() {
|
||||
return impl->Regs();
|
||||
return GetImpl(*this)->Regs();
|
||||
}
|
||||
|
||||
const std::array<std::uint32_t, 16>& Jit::Regs() const {
|
||||
return impl->Regs();
|
||||
return GetImpl(*this)->Regs();
|
||||
}
|
||||
|
||||
std::array<std::uint32_t, 64>& Jit::ExtRegs() {
|
||||
return impl->ExtRegs();
|
||||
return GetImpl(*this)->ExtRegs();
|
||||
}
|
||||
|
||||
const std::array<std::uint32_t, 64>& Jit::ExtRegs() const {
|
||||
return impl->ExtRegs();
|
||||
return GetImpl(*this)->ExtRegs();
|
||||
}
|
||||
|
||||
std::uint32_t Jit::Cpsr() const {
|
||||
return impl->Cpsr();
|
||||
return GetImpl(*this)->Cpsr();
|
||||
}
|
||||
|
||||
void Jit::SetCpsr(std::uint32_t value) {
|
||||
impl->SetCpsr(value);
|
||||
GetImpl(*this)->SetCpsr(value);
|
||||
}
|
||||
|
||||
std::uint32_t Jit::Fpscr() const {
|
||||
return impl->Fpscr();
|
||||
return GetImpl(*this)->Fpscr();
|
||||
}
|
||||
|
||||
void Jit::SetFpscr(std::uint32_t value) {
|
||||
impl->SetFpscr(value);
|
||||
GetImpl(*this)->SetFpscr(value);
|
||||
}
|
||||
|
||||
void Jit::ClearExclusiveState() {
|
||||
impl->ClearExclusiveState();
|
||||
GetImpl(*this)->ClearExclusiveState();
|
||||
}
|
||||
|
||||
std::string Jit::Disassemble() const {
|
||||
return impl->Disassemble();
|
||||
return GetImpl(*this)->Disassemble();
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::A32
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
|
|
@ -27,13 +27,13 @@ using namespace Backend::Arm64;
|
|||
|
||||
struct Jit::Impl final {
|
||||
Impl(Jit*, A64::UserConfig conf)
|
||||
: conf(conf)
|
||||
, current_address_space(conf)
|
||||
, core(conf) {}
|
||||
: conf(conf)
|
||||
, current_address_space(conf)
|
||||
, core(conf) {}
|
||||
|
||||
HaltReason Run() {
|
||||
ASSERT(!is_executing);
|
||||
PerformRequestedCacheInvalidation(static_cast<HaltReason>(Atomic::Load(&halt_reason)));
|
||||
PerformRequestedCacheInvalidation(HaltReason(Atomic::Load(&halt_reason)));
|
||||
|
||||
is_executing = true;
|
||||
SCOPE_EXIT {
|
||||
|
|
@ -49,7 +49,7 @@ struct Jit::Impl final {
|
|||
|
||||
HaltReason Step() {
|
||||
ASSERT(!is_executing);
|
||||
PerformRequestedCacheInvalidation(static_cast<HaltReason>(Atomic::Load(&halt_reason)));
|
||||
PerformRequestedCacheInvalidation(HaltReason(Atomic::Load(&halt_reason)));
|
||||
|
||||
is_executing = true;
|
||||
SCOPE_EXIT {
|
||||
|
|
@ -64,13 +64,11 @@ struct Jit::Impl final {
|
|||
}
|
||||
|
||||
void ClearCache() {
|
||||
std::unique_lock lock{invalidation_mutex};
|
||||
invalidate_entire_cache = true;
|
||||
HaltExecution(HaltReason::CacheInvalidation);
|
||||
}
|
||||
|
||||
void InvalidateCacheRange(std::uint64_t start_address, std::size_t length) {
|
||||
std::unique_lock lock{invalidation_mutex};
|
||||
invalid_cache_ranges.add(boost::icl::discrete_interval<u64>::closed(start_address, start_address + length - 1));
|
||||
HaltExecution(HaltReason::CacheInvalidation);
|
||||
}
|
||||
|
|
@ -158,8 +156,6 @@ struct Jit::Impl final {
|
|||
private:
|
||||
void PerformRequestedCacheInvalidation(HaltReason hr) {
|
||||
if (Has(hr, HaltReason::CacheInvalidation)) {
|
||||
std::unique_lock lock{invalidation_mutex};
|
||||
|
||||
ClearHalt(HaltReason::CacheInvalidation);
|
||||
|
||||
if (invalidate_entire_cache) {
|
||||
|
|
@ -185,134 +181,140 @@ private:
|
|||
A64Core core;
|
||||
|
||||
volatile u32 halt_reason = 0;
|
||||
|
||||
std::mutex invalidation_mutex;
|
||||
boost::icl::interval_set<u64> invalid_cache_ranges;
|
||||
bool invalidate_entire_cache = false;
|
||||
bool is_executing = false;
|
||||
};
|
||||
static_assert(sizeof(Jit::Impl) <= sizeof(Jit::impl_storage));
|
||||
|
||||
Jit::Jit(UserConfig conf)
|
||||
: impl{std::make_unique<Jit::Impl>(this, conf)} {
|
||||
Jit::Jit(UserConfig conf) {
|
||||
new (&impl_storage[0]) Jit::Impl(this, conf);
|
||||
}
|
||||
Jit::~Jit() {
|
||||
reinterpret_cast<Jit::Impl*>(&impl_storage[0])->~Impl();
|
||||
}
|
||||
inline Jit::Impl* GetImpl(Jit& jit) noexcept {
|
||||
return reinterpret_cast<Jit::Impl*>(&jit.impl_storage[0]);
|
||||
}
|
||||
inline Jit::Impl const* GetImpl(Jit const& jit) noexcept {
|
||||
return reinterpret_cast<Jit::Impl const*>(&jit.impl_storage[0]);
|
||||
}
|
||||
|
||||
Jit::~Jit() = default;
|
||||
|
||||
HaltReason Jit::Run() {
|
||||
return impl->Run();
|
||||
return GetImpl(*this)->Run();
|
||||
}
|
||||
|
||||
HaltReason Jit::Step() {
|
||||
return impl->Step();
|
||||
return GetImpl(*this)->Step();
|
||||
}
|
||||
|
||||
void Jit::ClearCache() {
|
||||
impl->ClearCache();
|
||||
GetImpl(*this)->ClearCache();
|
||||
}
|
||||
|
||||
void Jit::InvalidateCacheRange(std::uint64_t start_address, std::size_t length) {
|
||||
impl->InvalidateCacheRange(start_address, length);
|
||||
GetImpl(*this)->InvalidateCacheRange(start_address, length);
|
||||
}
|
||||
|
||||
void Jit::Reset() {
|
||||
impl->Reset();
|
||||
GetImpl(*this)->Reset();
|
||||
}
|
||||
|
||||
void Jit::HaltExecution(HaltReason hr) {
|
||||
impl->HaltExecution(hr);
|
||||
GetImpl(*this)->HaltExecution(hr);
|
||||
}
|
||||
|
||||
void Jit::ClearHalt(HaltReason hr) {
|
||||
impl->ClearHalt(hr);
|
||||
GetImpl(*this)->ClearHalt(hr);
|
||||
}
|
||||
|
||||
std::uint64_t Jit::GetSP() const {
|
||||
return impl->SP();
|
||||
return GetImpl(*this)->SP();
|
||||
}
|
||||
|
||||
void Jit::SetSP(std::uint64_t value) {
|
||||
impl->SetSP(value);
|
||||
GetImpl(*this)->SetSP(value);
|
||||
}
|
||||
|
||||
std::uint64_t Jit::GetPC() const {
|
||||
return impl->PC();
|
||||
return GetImpl(*this)->PC();
|
||||
}
|
||||
|
||||
void Jit::SetPC(std::uint64_t value) {
|
||||
impl->SetPC(value);
|
||||
GetImpl(*this)->SetPC(value);
|
||||
}
|
||||
|
||||
std::uint64_t Jit::GetRegister(std::size_t index) const {
|
||||
return impl->Regs()[index];
|
||||
return GetImpl(*this)->Regs()[index];
|
||||
}
|
||||
|
||||
void Jit::SetRegister(size_t index, std::uint64_t value) {
|
||||
impl->Regs()[index] = value;
|
||||
GetImpl(*this)->Regs()[index] = value;
|
||||
}
|
||||
|
||||
std::array<std::uint64_t, 31> Jit::GetRegisters() const {
|
||||
return impl->Regs();
|
||||
return GetImpl(*this)->Regs();
|
||||
}
|
||||
|
||||
void Jit::SetRegisters(const std::array<std::uint64_t, 31>& value) {
|
||||
impl->Regs() = value;
|
||||
GetImpl(*this)->Regs() = value;
|
||||
}
|
||||
|
||||
Vector Jit::GetVector(std::size_t index) const {
|
||||
auto& vec = impl->VecRegs();
|
||||
auto& vec = GetImpl(*this)->VecRegs();
|
||||
return {vec[index * 2], vec[index * 2 + 1]};
|
||||
}
|
||||
|
||||
void Jit::SetVector(std::size_t index, Vector value) {
|
||||
auto& vec = impl->VecRegs();
|
||||
auto& vec = GetImpl(*this)->VecRegs();
|
||||
vec[index * 2] = value[0];
|
||||
vec[index * 2 + 1] = value[1];
|
||||
}
|
||||
|
||||
std::array<Vector, 32> Jit::GetVectors() const {
|
||||
std::array<Vector, 32> ret;
|
||||
std::memcpy(ret.data(), impl->VecRegs().data(), sizeof(ret));
|
||||
std::memcpy(ret.data(), GetImpl(*this)->VecRegs().data(), sizeof(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Jit::SetVectors(const std::array<Vector, 32>& value) {
|
||||
std::memcpy(impl->VecRegs().data(), value.data(), sizeof(value));
|
||||
std::memcpy(GetImpl(*this)->VecRegs().data(), value.data(), sizeof(value));
|
||||
}
|
||||
|
||||
std::uint32_t Jit::GetFpcr() const {
|
||||
return impl->Fpcr();
|
||||
return GetImpl(*this)->Fpcr();
|
||||
}
|
||||
|
||||
void Jit::SetFpcr(std::uint32_t value) {
|
||||
impl->SetFpcr(value);
|
||||
GetImpl(*this)->SetFpcr(value);
|
||||
}
|
||||
|
||||
std::uint32_t Jit::GetFpsr() const {
|
||||
return impl->Fpsr();
|
||||
return GetImpl(*this)->Fpsr();
|
||||
}
|
||||
|
||||
void Jit::SetFpsr(std::uint32_t value) {
|
||||
impl->SetFpsr(value);
|
||||
GetImpl(*this)->SetFpsr(value);
|
||||
}
|
||||
|
||||
std::uint32_t Jit::GetPstate() const {
|
||||
return impl->Pstate();
|
||||
return GetImpl(*this)->Pstate();
|
||||
}
|
||||
|
||||
void Jit::SetPstate(std::uint32_t value) {
|
||||
impl->SetPstate(value);
|
||||
GetImpl(*this)->SetPstate(value);
|
||||
}
|
||||
|
||||
void Jit::ClearExclusiveState() {
|
||||
impl->ClearExclusiveState();
|
||||
GetImpl(*this)->ClearExclusiveState();
|
||||
}
|
||||
|
||||
bool Jit::IsExecuting() const {
|
||||
return impl->IsExecuting();
|
||||
return GetImpl(*this)->IsExecuting();
|
||||
}
|
||||
|
||||
std::string Jit::Disassemble() const {
|
||||
return impl->Disassemble();
|
||||
return GetImpl(*this)->Disassemble();
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::A64
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
|
|
@ -60,13 +60,11 @@ struct Jit::Impl final {
|
|||
}
|
||||
|
||||
void ClearCache() {
|
||||
std::unique_lock lock{invalidation_mutex};
|
||||
invalidate_entire_cache = true;
|
||||
HaltExecution(HaltReason::CacheInvalidation);
|
||||
}
|
||||
|
||||
void InvalidateCacheRange(u32 start_address, size_t length) {
|
||||
std::unique_lock lock{invalidation_mutex};
|
||||
invalid_cache_ranges.add(boost::icl::discrete_interval<u32>::closed(start_address, static_cast<u32>(start_address + length - 1)));
|
||||
HaltExecution(HaltReason::CacheInvalidation);
|
||||
}
|
||||
|
|
@ -134,79 +132,86 @@ private:
|
|||
A32Core core;
|
||||
|
||||
volatile u32 halt_reason = 0;
|
||||
|
||||
std::mutex invalidation_mutex;
|
||||
boost::icl::interval_set<u32> invalid_cache_ranges;
|
||||
bool invalidate_entire_cache = false;
|
||||
};
|
||||
static_assert(sizeof(Jit::Impl) <= sizeof(Jit::impl_storage));
|
||||
|
||||
Jit::Jit(UserConfig conf)
|
||||
: impl(std::make_unique<Impl>(this, conf)) {}
|
||||
|
||||
Jit::~Jit() = default;
|
||||
Jit::Jit(UserConfig conf) {
|
||||
new (&impl_storage[0]) Jit::Impl(this, conf);
|
||||
}
|
||||
Jit::~Jit() {
|
||||
reinterpret_cast<Jit::Impl*>(&impl_storage[0])->~Impl();
|
||||
}
|
||||
inline Jit::Impl* GetImpl(Jit& jit) noexcept {
|
||||
return reinterpret_cast<Jit::Impl*>(&jit.impl_storage[0]);
|
||||
}
|
||||
inline Jit::Impl const* GetImpl(Jit const& jit) noexcept {
|
||||
return reinterpret_cast<Jit::Impl const*>(&jit.impl_storage[0]);
|
||||
}
|
||||
|
||||
HaltReason Jit::Run() {
|
||||
return impl->Run();
|
||||
return GetImpl(*this)->Run();
|
||||
}
|
||||
|
||||
HaltReason Jit::Step() {
|
||||
return impl->Step();
|
||||
return GetImpl(*this)->Step();
|
||||
}
|
||||
|
||||
void Jit::ClearCache() {
|
||||
impl->ClearCache();
|
||||
GetImpl(*this)->ClearCache();
|
||||
}
|
||||
|
||||
void Jit::InvalidateCacheRange(u32 start_address, std::size_t length) {
|
||||
impl->InvalidateCacheRange(start_address, length);
|
||||
GetImpl(*this)->InvalidateCacheRange(start_address, length);
|
||||
}
|
||||
|
||||
void Jit::Reset() {
|
||||
impl->Reset();
|
||||
GetImpl(*this)->Reset();
|
||||
}
|
||||
|
||||
void Jit::HaltExecution(HaltReason hr) {
|
||||
impl->HaltExecution(hr);
|
||||
GetImpl(*this)->HaltExecution(hr);
|
||||
}
|
||||
|
||||
void Jit::ClearHalt(HaltReason hr) {
|
||||
impl->ClearHalt(hr);
|
||||
GetImpl(*this)->ClearHalt(hr);
|
||||
}
|
||||
|
||||
std::array<u32, 16>& Jit::Regs() {
|
||||
return impl->Regs();
|
||||
return GetImpl(*this)->Regs();
|
||||
}
|
||||
|
||||
const std::array<u32, 16>& Jit::Regs() const {
|
||||
return impl->Regs();
|
||||
return GetImpl(*this)->Regs();
|
||||
}
|
||||
|
||||
std::array<u32, 64>& Jit::ExtRegs() {
|
||||
return impl->ExtRegs();
|
||||
return GetImpl(*this)->ExtRegs();
|
||||
}
|
||||
|
||||
const std::array<u32, 64>& Jit::ExtRegs() const {
|
||||
return impl->ExtRegs();
|
||||
return GetImpl(*this)->ExtRegs();
|
||||
}
|
||||
|
||||
u32 Jit::Cpsr() const {
|
||||
return impl->Cpsr();
|
||||
return GetImpl(*this)->Cpsr();
|
||||
}
|
||||
|
||||
void Jit::SetCpsr(u32 value) {
|
||||
impl->SetCpsr(value);
|
||||
GetImpl(*this)->SetCpsr(value);
|
||||
}
|
||||
|
||||
u32 Jit::Fpscr() const {
|
||||
return impl->Fpscr();
|
||||
return GetImpl(*this)->Fpscr();
|
||||
}
|
||||
|
||||
void Jit::SetFpscr(u32 value) {
|
||||
impl->SetFpscr(value);
|
||||
GetImpl(*this)->SetFpscr(value);
|
||||
}
|
||||
|
||||
void Jit::ClearExclusiveState() {
|
||||
impl->ClearExclusiveState();
|
||||
GetImpl(*this)->ClearExclusiveState();
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::A32
|
||||
|
|
|
|||
|
|
@ -81,7 +81,10 @@ FP::FPCR A32EmitContext::FPCR(bool fpcr_controlled) const {
|
|||
}
|
||||
|
||||
A32EmitX64::A32EmitX64(BlockOfCode& code, A32::UserConfig conf, A32::Jit* jit_interface)
|
||||
: EmitX64(code), conf(std::move(conf)), jit_interface(jit_interface) {
|
||||
: EmitX64(code)
|
||||
, conf(std::move(conf))
|
||||
, jit_interface(jit_interface)
|
||||
{
|
||||
GenFastmemFallbacks();
|
||||
GenTerminalHandlers();
|
||||
code.PreludeComplete();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
|
|
@ -116,13 +116,11 @@ struct Jit::Impl {
|
|||
}
|
||||
|
||||
void ClearCache() {
|
||||
std::unique_lock lock{invalidation_mutex};
|
||||
invalidate_entire_cache = true;
|
||||
HaltExecution(HaltReason::CacheInvalidation);
|
||||
}
|
||||
|
||||
void InvalidateCacheRange(std::uint32_t start_address, std::size_t length) {
|
||||
std::unique_lock lock{invalidation_mutex};
|
||||
invalid_cache_ranges.add(boost::icl::discrete_interval<u32>::closed(start_address, static_cast<u32>(start_address + length - 1)));
|
||||
HaltExecution(HaltReason::CacheInvalidation);
|
||||
}
|
||||
|
|
@ -219,8 +217,6 @@ private:
|
|||
|
||||
void PerformRequestedCacheInvalidation(HaltReason hr) {
|
||||
if (Has(hr, HaltReason::CacheInvalidation)) {
|
||||
std::unique_lock lock{invalidation_mutex};
|
||||
|
||||
ClearHalt(HaltReason::CacheInvalidation);
|
||||
|
||||
if (!invalidate_entire_cache && invalid_cache_ranges.empty()) {
|
||||
|
|
@ -251,80 +247,88 @@ private:
|
|||
// Requests made during execution to invalidate the cache are queued up here.
|
||||
bool invalidate_entire_cache = false;
|
||||
boost::icl::interval_set<u32> invalid_cache_ranges;
|
||||
std::mutex invalidation_mutex;
|
||||
};
|
||||
static_assert(sizeof(Jit::Impl) <= sizeof(Jit::impl_storage));
|
||||
|
||||
Jit::Jit(UserConfig conf)
|
||||
: impl(std::make_unique<Impl>(this, std::move(conf))) {}
|
||||
|
||||
Jit::~Jit() = default;
|
||||
Jit::Jit(UserConfig conf) {
|
||||
new (&impl_storage[0]) Jit::Impl(this, conf);
|
||||
}
|
||||
Jit::~Jit() {
|
||||
reinterpret_cast<Jit::Impl*>(&impl_storage[0])->~Impl();
|
||||
}
|
||||
inline Jit::Impl* GetImpl(Jit& jit) noexcept {
|
||||
return reinterpret_cast<Jit::Impl*>(&jit.impl_storage[0]);
|
||||
}
|
||||
inline Jit::Impl const* GetImpl(Jit const& jit) noexcept {
|
||||
return reinterpret_cast<Jit::Impl const*>(&jit.impl_storage[0]);
|
||||
}
|
||||
|
||||
HaltReason Jit::Run() {
|
||||
return impl->Run();
|
||||
return GetImpl(*this)->Run();
|
||||
}
|
||||
|
||||
HaltReason Jit::Step() {
|
||||
return impl->Step();
|
||||
return GetImpl(*this)->Step();
|
||||
}
|
||||
|
||||
void Jit::ClearCache() {
|
||||
impl->ClearCache();
|
||||
GetImpl(*this)->ClearCache();
|
||||
}
|
||||
|
||||
void Jit::InvalidateCacheRange(std::uint32_t start_address, std::size_t length) {
|
||||
impl->InvalidateCacheRange(start_address, length);
|
||||
GetImpl(*this)->InvalidateCacheRange(start_address, length);
|
||||
}
|
||||
|
||||
void Jit::Reset() {
|
||||
impl->Reset();
|
||||
GetImpl(*this)->Reset();
|
||||
}
|
||||
|
||||
void Jit::HaltExecution(HaltReason hr) {
|
||||
impl->HaltExecution(hr);
|
||||
GetImpl(*this)->HaltExecution(hr);
|
||||
}
|
||||
|
||||
void Jit::ClearHalt(HaltReason hr) {
|
||||
impl->ClearHalt(hr);
|
||||
GetImpl(*this)->ClearHalt(hr);
|
||||
}
|
||||
|
||||
std::array<std::uint32_t, 16>& Jit::Regs() {
|
||||
return impl->Regs();
|
||||
return GetImpl(*this)->Regs();
|
||||
}
|
||||
|
||||
const std::array<std::uint32_t, 16>& Jit::Regs() const {
|
||||
return impl->Regs();
|
||||
return GetImpl(*this)->Regs();
|
||||
}
|
||||
|
||||
std::array<std::uint32_t, 64>& Jit::ExtRegs() {
|
||||
return impl->ExtRegs();
|
||||
return GetImpl(*this)->ExtRegs();
|
||||
}
|
||||
|
||||
const std::array<std::uint32_t, 64>& Jit::ExtRegs() const {
|
||||
return impl->ExtRegs();
|
||||
return GetImpl(*this)->ExtRegs();
|
||||
}
|
||||
|
||||
std::uint32_t Jit::Cpsr() const {
|
||||
return impl->Cpsr();
|
||||
return GetImpl(*this)->Cpsr();
|
||||
}
|
||||
|
||||
void Jit::SetCpsr(std::uint32_t value) {
|
||||
impl->SetCpsr(value);
|
||||
GetImpl(*this)->SetCpsr(value);
|
||||
}
|
||||
|
||||
std::uint32_t Jit::Fpscr() const {
|
||||
return impl->Fpscr();
|
||||
return GetImpl(*this)->Fpscr();
|
||||
}
|
||||
|
||||
void Jit::SetFpscr(std::uint32_t value) {
|
||||
impl->SetFpscr(value);
|
||||
GetImpl(*this)->SetFpscr(value);
|
||||
}
|
||||
|
||||
void Jit::ClearExclusiveState() {
|
||||
impl->ClearExclusiveState();
|
||||
GetImpl(*this)->ClearExclusiveState();
|
||||
}
|
||||
|
||||
std::string Jit::Disassemble() const {
|
||||
return impl->Disassemble();
|
||||
return GetImpl(*this)->Disassemble();
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::A32
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
|
|
@ -115,14 +115,12 @@ public:
|
|||
}
|
||||
|
||||
void ClearCache() {
|
||||
std::unique_lock lock{invalidation_mutex};
|
||||
invalidate_entire_cache = true;
|
||||
HaltExecution(HaltReason::CacheInvalidation);
|
||||
}
|
||||
|
||||
void InvalidateCacheRange(u64 start_address, size_t length) {
|
||||
std::unique_lock lock{invalidation_mutex};
|
||||
const auto end_address = static_cast<u64>(start_address + length - 1);
|
||||
const auto end_address = u64(start_address + length - 1);
|
||||
const auto range = boost::icl::discrete_interval<u64>::closed(start_address, end_address);
|
||||
invalid_cache_ranges.add(range);
|
||||
HaltExecution(HaltReason::CacheInvalidation);
|
||||
|
|
@ -276,8 +274,6 @@ private:
|
|||
|
||||
void PerformRequestedCacheInvalidation(HaltReason hr) {
|
||||
if (Has(hr, HaltReason::CacheInvalidation)) {
|
||||
std::unique_lock lock{invalidation_mutex};
|
||||
|
||||
ClearHalt(HaltReason::CacheInvalidation);
|
||||
|
||||
if (!invalidate_entire_cache && invalid_cache_ranges.empty()) {
|
||||
|
|
@ -306,124 +302,132 @@ private:
|
|||
|
||||
bool invalidate_entire_cache = false;
|
||||
boost::icl::interval_set<u64> invalid_cache_ranges;
|
||||
std::mutex invalidation_mutex;
|
||||
};
|
||||
static_assert(sizeof(Jit::Impl) <= sizeof(Jit::impl_storage));
|
||||
|
||||
Jit::Jit(UserConfig conf)
|
||||
: impl(std::make_unique<Jit::Impl>(this, conf)) {}
|
||||
|
||||
Jit::~Jit() = default;
|
||||
Jit::Jit(UserConfig conf) {
|
||||
new (&impl_storage[0]) Jit::Impl(this, conf);
|
||||
}
|
||||
Jit::~Jit() {
|
||||
reinterpret_cast<Jit::Impl*>(&impl_storage[0])->~Impl();
|
||||
}
|
||||
inline Jit::Impl* GetImpl(Jit& jit) noexcept {
|
||||
return reinterpret_cast<Jit::Impl*>(&jit.impl_storage[0]);
|
||||
}
|
||||
inline Jit::Impl const* GetImpl(Jit const& jit) noexcept {
|
||||
return reinterpret_cast<Jit::Impl const*>(&jit.impl_storage[0]);
|
||||
}
|
||||
|
||||
HaltReason Jit::Run() {
|
||||
return impl->Run();
|
||||
return GetImpl(*this)->Run();
|
||||
}
|
||||
|
||||
HaltReason Jit::Step() {
|
||||
return impl->Step();
|
||||
return GetImpl(*this)->Step();
|
||||
}
|
||||
|
||||
void Jit::ClearCache() {
|
||||
impl->ClearCache();
|
||||
GetImpl(*this)->ClearCache();
|
||||
}
|
||||
|
||||
void Jit::InvalidateCacheRange(u64 start_address, size_t length) {
|
||||
impl->InvalidateCacheRange(start_address, length);
|
||||
GetImpl(*this)->InvalidateCacheRange(start_address, length);
|
||||
}
|
||||
|
||||
void Jit::Reset() {
|
||||
impl->Reset();
|
||||
GetImpl(*this)->Reset();
|
||||
}
|
||||
|
||||
void Jit::HaltExecution(HaltReason hr) {
|
||||
impl->HaltExecution(hr);
|
||||
GetImpl(*this)->HaltExecution(hr);
|
||||
}
|
||||
|
||||
void Jit::ClearHalt(HaltReason hr) {
|
||||
impl->ClearHalt(hr);
|
||||
GetImpl(*this)->ClearHalt(hr);
|
||||
}
|
||||
|
||||
u64 Jit::GetSP() const {
|
||||
return impl->GetSP();
|
||||
return GetImpl(*this)->GetSP();
|
||||
}
|
||||
|
||||
void Jit::SetSP(u64 value) {
|
||||
impl->SetSP(value);
|
||||
GetImpl(*this)->SetSP(value);
|
||||
}
|
||||
|
||||
u64 Jit::GetPC() const {
|
||||
return impl->GetPC();
|
||||
return GetImpl(*this)->GetPC();
|
||||
}
|
||||
|
||||
void Jit::SetPC(u64 value) {
|
||||
impl->SetPC(value);
|
||||
GetImpl(*this)->SetPC(value);
|
||||
}
|
||||
|
||||
u64 Jit::GetRegister(size_t index) const {
|
||||
return impl->GetRegister(index);
|
||||
return GetImpl(*this)->GetRegister(index);
|
||||
}
|
||||
|
||||
void Jit::SetRegister(size_t index, u64 value) {
|
||||
impl->SetRegister(index, value);
|
||||
GetImpl(*this)->SetRegister(index, value);
|
||||
}
|
||||
|
||||
std::array<u64, 31> Jit::GetRegisters() const {
|
||||
return impl->GetRegisters();
|
||||
return GetImpl(*this)->GetRegisters();
|
||||
}
|
||||
|
||||
void Jit::SetRegisters(const std::array<u64, 31>& value) {
|
||||
impl->SetRegisters(value);
|
||||
GetImpl(*this)->SetRegisters(value);
|
||||
}
|
||||
|
||||
Vector Jit::GetVector(size_t index) const {
|
||||
return impl->GetVector(index);
|
||||
return GetImpl(*this)->GetVector(index);
|
||||
}
|
||||
|
||||
void Jit::SetVector(size_t index, Vector value) {
|
||||
impl->SetVector(index, value);
|
||||
GetImpl(*this)->SetVector(index, value);
|
||||
}
|
||||
|
||||
std::array<Vector, 32> Jit::GetVectors() const {
|
||||
return impl->GetVectors();
|
||||
return GetImpl(*this)->GetVectors();
|
||||
}
|
||||
|
||||
void Jit::SetVectors(const std::array<Vector, 32>& value) {
|
||||
impl->SetVectors(value);
|
||||
GetImpl(*this)->SetVectors(value);
|
||||
}
|
||||
|
||||
u32 Jit::GetFpcr() const {
|
||||
return impl->GetFpcr();
|
||||
return GetImpl(*this)->GetFpcr();
|
||||
}
|
||||
|
||||
void Jit::SetFpcr(u32 value) {
|
||||
impl->SetFpcr(value);
|
||||
GetImpl(*this)->SetFpcr(value);
|
||||
}
|
||||
|
||||
u32 Jit::GetFpsr() const {
|
||||
return impl->GetFpsr();
|
||||
return GetImpl(*this)->GetFpsr();
|
||||
}
|
||||
|
||||
void Jit::SetFpsr(u32 value) {
|
||||
impl->SetFpsr(value);
|
||||
GetImpl(*this)->SetFpsr(value);
|
||||
}
|
||||
|
||||
u32 Jit::GetPstate() const {
|
||||
return impl->GetPstate();
|
||||
return GetImpl(*this)->GetPstate();
|
||||
}
|
||||
|
||||
void Jit::SetPstate(u32 value) {
|
||||
impl->SetPstate(value);
|
||||
GetImpl(*this)->SetPstate(value);
|
||||
}
|
||||
|
||||
void Jit::ClearExclusiveState() {
|
||||
impl->ClearExclusiveState();
|
||||
GetImpl(*this)->ClearExclusiveState();
|
||||
}
|
||||
|
||||
bool Jit::IsExecuting() const {
|
||||
return impl->IsExecuting();
|
||||
return GetImpl(*this)->IsExecuting();
|
||||
}
|
||||
|
||||
std::string Jit::Disassemble() const {
|
||||
return impl->Disassemble();
|
||||
return GetImpl(*this)->Disassemble();
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::A64
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
|
|
@ -197,8 +197,8 @@ private:
|
|||
RunCodeFuncType run_code = nullptr;
|
||||
RunCodeFuncType step_code = nullptr;
|
||||
std::array<const void*, 4> return_from_run_code;
|
||||
bool prelude_complete = false;
|
||||
const HostFeature host_features;
|
||||
bool prelude_complete = false;
|
||||
|
||||
void GenRunCode(std::function<void(BlockOfCode&)> rcp);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
|
|
@ -96,11 +96,9 @@ public:
|
|||
/// the resulting instructions as a vector of their string representations.
|
||||
std::string Disassemble() const;
|
||||
|
||||
private:
|
||||
bool is_executing = false;
|
||||
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
bool is_executing = false;
|
||||
char impl_storage[16788736];
|
||||
};
|
||||
|
||||
} // namespace A32
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
|
|
@ -126,9 +126,8 @@ public:
|
|||
/// the resulting instructions as a vector of their string representations.
|
||||
std::string Disassemble() const;
|
||||
|
||||
private:
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
char impl_storage[16788736];
|
||||
};
|
||||
|
||||
} // namespace A64
|
||||
|
|
|
|||
Loading…
Reference in New Issue