mirror of
https://github.com/yuzu-mirror/dynarmic.git
synced 2026-02-12 10:14:14 +01:00
270 lines
5.9 KiB
C++
270 lines
5.9 KiB
C++
/* This file is part of the dynarmic project.
|
|
* Copyright (c) 2021 MerryMage
|
|
* SPDX-License-Identifier: 0BSD
|
|
*/
|
|
|
|
#include <memory>
|
|
#include <mutex>
|
|
|
|
#include <boost/icl/interval_set.hpp>
|
|
#include <mcl/assert.hpp>
|
|
#include <mcl/scope_exit.hpp>
|
|
#include <mcl/stdint.hpp>
|
|
|
|
#include "dynarmic/backend/arm64/a32_address_space.h"
|
|
#include "dynarmic/backend/arm64/a32_core.h"
|
|
#include "dynarmic/backend/arm64/a32_jitstate.h"
|
|
#include "dynarmic/common/atomic.h"
|
|
#include "dynarmic/interface/A32/a32.h"
|
|
#include "dynarmic/interface/A32/context.h"
|
|
|
|
namespace Dynarmic::A32 {
|
|
|
|
using namespace Backend::Arm64;
|
|
|
|
struct Context::Impl {
|
|
A32JitState state;
|
|
};
|
|
|
|
Context::Context()
|
|
: impl(std::make_unique<Context::Impl>()) {}
|
|
|
|
Context::~Context() = default;
|
|
|
|
Context::Context(const Context& ctx)
|
|
: impl(std::make_unique<Context::Impl>(*ctx.impl)) {}
|
|
|
|
Context::Context(Context&& ctx) noexcept
|
|
: impl(std::move(ctx.impl)) {}
|
|
|
|
Context& Context::operator=(const Context& ctx) {
|
|
*impl = *ctx.impl;
|
|
return *this;
|
|
}
|
|
|
|
Context& Context::operator=(Context&& ctx) noexcept {
|
|
impl = std::move(ctx.impl);
|
|
return *this;
|
|
}
|
|
|
|
struct Jit::Impl final {
|
|
Impl(Jit* jit_interface, A32::UserConfig conf)
|
|
: jit_interface(jit_interface)
|
|
, conf(conf)
|
|
, current_address_space(conf)
|
|
, core(conf) {}
|
|
|
|
HaltReason Run() {
|
|
ASSERT(!jit_interface->is_executing);
|
|
jit_interface->is_executing = true;
|
|
SCOPE_EXIT {
|
|
jit_interface->is_executing = false;
|
|
};
|
|
|
|
HaltReason hr = core.Run(current_address_space, current_state, &halt_reason);
|
|
|
|
RequestCacheInvalidation();
|
|
|
|
return hr;
|
|
}
|
|
|
|
HaltReason Step() {
|
|
ASSERT(!jit_interface->is_executing);
|
|
jit_interface->is_executing = true;
|
|
SCOPE_EXIT {
|
|
jit_interface->is_executing = false;
|
|
};
|
|
|
|
ASSERT_FALSE("Unimplemented");
|
|
|
|
RequestCacheInvalidation();
|
|
|
|
return HaltReason{};
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
void Reset() {
|
|
current_state = {};
|
|
}
|
|
|
|
void HaltExecution(HaltReason hr) {
|
|
Atomic::Or(&halt_reason, ~static_cast<u32>(hr));
|
|
}
|
|
|
|
void ClearHalt(HaltReason hr) {
|
|
Atomic::And(&halt_reason, ~static_cast<u32>(hr));
|
|
}
|
|
|
|
std::array<std::uint32_t, 16>& Regs() {
|
|
return current_state.regs;
|
|
}
|
|
|
|
const std::array<std::uint32_t, 16>& Regs() const {
|
|
return current_state.regs;
|
|
}
|
|
|
|
std::array<std::uint32_t, 64>& ExtRegs() {
|
|
return current_state.ext_regs;
|
|
}
|
|
|
|
const std::array<std::uint32_t, 64>& ExtRegs() const {
|
|
return current_state.ext_regs;
|
|
}
|
|
|
|
std::uint32_t Cpsr() const {
|
|
return current_state.Cpsr();
|
|
}
|
|
|
|
void SetCpsr(std::uint32_t value) {
|
|
current_state.SetCpsr(value);
|
|
}
|
|
|
|
std::uint32_t Fpscr() const {
|
|
return current_state.Fpscr();
|
|
}
|
|
|
|
void SetFpscr(std::uint32_t value) {
|
|
current_state.SetFpscr(value);
|
|
}
|
|
|
|
Context SaveContext() const {
|
|
Context ctx;
|
|
ctx.impl->state = current_state;
|
|
return ctx;
|
|
}
|
|
|
|
void SaveContext(Context& ctx) const {
|
|
ctx.impl->state = current_state;
|
|
}
|
|
|
|
void LoadContext(const Context& ctx) {
|
|
current_state = ctx.impl->state;
|
|
}
|
|
|
|
void ClearExclusiveState() {
|
|
current_state.exclusive_state = false;
|
|
}
|
|
|
|
void DumpDisassembly() const {
|
|
ASSERT_FALSE("Unimplemented");
|
|
}
|
|
|
|
private:
|
|
void RequestCacheInvalidation() {
|
|
// ASSERT_FALSE("Unimplemented");
|
|
|
|
invalidate_entire_cache = false;
|
|
invalid_cache_ranges.clear();
|
|
}
|
|
|
|
Jit* jit_interface;
|
|
A32::UserConfig conf;
|
|
A32JitState current_state{};
|
|
A32AddressSpace current_address_space;
|
|
A32Core core;
|
|
|
|
volatile u32 halt_reason = 0;
|
|
|
|
std::mutex invalidation_mutex;
|
|
boost::icl::interval_set<u32> invalid_cache_ranges;
|
|
bool invalidate_entire_cache = false;
|
|
};
|
|
|
|
Jit::Jit(UserConfig conf)
|
|
: impl(std::make_unique<Impl>(this, conf)) {}
|
|
|
|
Jit::~Jit() = default;
|
|
|
|
HaltReason Jit::Run() {
|
|
return impl->Run();
|
|
}
|
|
|
|
HaltReason Jit::Step() {
|
|
return impl->Step();
|
|
}
|
|
|
|
void Jit::ClearCache() {
|
|
impl->ClearCache();
|
|
}
|
|
|
|
void Jit::InvalidateCacheRange(std::uint32_t start_address, std::size_t length) {
|
|
impl->InvalidateCacheRange(start_address, length);
|
|
}
|
|
|
|
void Jit::Reset() {
|
|
impl->Reset();
|
|
}
|
|
|
|
void Jit::HaltExecution(HaltReason hr) {
|
|
impl->HaltExecution(hr);
|
|
}
|
|
|
|
void Jit::ClearHalt(HaltReason hr) {
|
|
impl->ClearHalt(hr);
|
|
}
|
|
|
|
std::array<std::uint32_t, 16>& Jit::Regs() {
|
|
return impl->Regs();
|
|
}
|
|
|
|
const std::array<std::uint32_t, 16>& Jit::Regs() const {
|
|
return impl->Regs();
|
|
}
|
|
|
|
std::array<std::uint32_t, 64>& Jit::ExtRegs() {
|
|
return impl->ExtRegs();
|
|
}
|
|
|
|
const std::array<std::uint32_t, 64>& Jit::ExtRegs() const {
|
|
return impl->ExtRegs();
|
|
}
|
|
|
|
std::uint32_t Jit::Cpsr() const {
|
|
return impl->Cpsr();
|
|
}
|
|
|
|
void Jit::SetCpsr(std::uint32_t value) {
|
|
impl->SetCpsr(value);
|
|
}
|
|
|
|
std::uint32_t Jit::Fpscr() const {
|
|
return impl->Fpscr();
|
|
}
|
|
|
|
void Jit::SetFpscr(std::uint32_t value) {
|
|
impl->SetFpscr(value);
|
|
}
|
|
|
|
Context Jit::SaveContext() const {
|
|
return impl->SaveContext();
|
|
}
|
|
|
|
void Jit::SaveContext(Context& ctx) const {
|
|
impl->SaveContext(ctx);
|
|
}
|
|
|
|
void Jit::LoadContext(const Context& ctx) {
|
|
impl->LoadContext(ctx);
|
|
}
|
|
|
|
void Jit::ClearExclusiveState() {
|
|
impl->ClearExclusiveState();
|
|
}
|
|
|
|
void Jit::DumpDisassembly() const {
|
|
impl->DumpDisassembly();
|
|
}
|
|
|
|
} // namespace Dynarmic::A32
|