interface: Allow saving and storing of contexts
This commit is contained in:
parent
19a7fb8992
commit
4393473d06
4 changed files with 140 additions and 1 deletions
44
include/dynarmic/context.h
Normal file
44
include/dynarmic/context.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2016 MerryMage
|
||||||
|
* This software may be used and distributed according to the terms of the GNU
|
||||||
|
* General Public License version 2 or any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace Dynarmic {
|
||||||
|
|
||||||
|
struct Context {
|
||||||
|
public:
|
||||||
|
Context();
|
||||||
|
~Context();
|
||||||
|
Context(const Context&);
|
||||||
|
Context(Context&&);
|
||||||
|
Context& operator=(const Context&);
|
||||||
|
Context& operator=(Context&&);
|
||||||
|
|
||||||
|
/// View and modify registers.
|
||||||
|
std::array<std::uint32_t, 16>& Regs();
|
||||||
|
const std::array<std::uint32_t, 16>& Regs() const;
|
||||||
|
std::array<std::uint32_t, 64>& ExtRegs();
|
||||||
|
const std::array<std::uint32_t, 64>& ExtRegs() const;
|
||||||
|
|
||||||
|
/// View and modify CPSR.
|
||||||
|
std::uint32_t Cpsr() const;
|
||||||
|
void SetCpsr(std::uint32_t value);
|
||||||
|
|
||||||
|
/// View and modify FPSCR.
|
||||||
|
std::uint32_t Fpscr() const;
|
||||||
|
void SetFpscr(std::uint32_t value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class Jit;
|
||||||
|
struct Impl;
|
||||||
|
std::unique_ptr<Impl> impl;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Dynarmic
|
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
namespace Dynarmic {
|
namespace Dynarmic {
|
||||||
|
|
||||||
|
struct Context;
|
||||||
|
|
||||||
namespace IR {
|
namespace IR {
|
||||||
class LocationDescriptor;
|
class LocationDescriptor;
|
||||||
}
|
}
|
||||||
|
@ -70,6 +72,10 @@ public:
|
||||||
std::uint32_t Fpscr() const;
|
std::uint32_t Fpscr() const;
|
||||||
void SetFpscr(std::uint32_t value);
|
void SetFpscr(std::uint32_t value);
|
||||||
|
|
||||||
|
Context SaveContext() const;
|
||||||
|
void SaveContext(Context&) const;
|
||||||
|
void LoadContext(const Context&);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if Jit::Run was called but hasn't returned yet.
|
* Returns true if Jit::Run was called but hasn't returned yet.
|
||||||
* i.e.: We're in a callback.
|
* i.e.: We're in a callback.
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/scope_exit.h"
|
#include "common/scope_exit.h"
|
||||||
|
#include "dynarmic/context.h"
|
||||||
#include "dynarmic/dynarmic.h"
|
#include "dynarmic/dynarmic.h"
|
||||||
#include "frontend/ir/basic_block.h"
|
#include "frontend/ir/basic_block.h"
|
||||||
#include "frontend/ir/location_descriptor.h"
|
#include "frontend/ir/location_descriptor.h"
|
||||||
|
@ -45,6 +46,7 @@ struct Jit::Impl {
|
||||||
const UserCallbacks callbacks;
|
const UserCallbacks callbacks;
|
||||||
|
|
||||||
// Requests made during execution to invalidate the cache are queued up here.
|
// Requests made during execution to invalidate the cache are queued up here.
|
||||||
|
size_t invalid_cache_generation = 0;
|
||||||
boost::icl::interval_set<u32> invalid_cache_ranges;
|
boost::icl::interval_set<u32> invalid_cache_ranges;
|
||||||
bool invalidate_entire_cache = false;
|
bool invalidate_entire_cache = false;
|
||||||
|
|
||||||
|
@ -98,6 +100,7 @@ struct Jit::Impl {
|
||||||
|
|
||||||
invalid_cache_ranges.clear();
|
invalid_cache_ranges.clear();
|
||||||
invalidate_entire_cache = false;
|
invalidate_entire_cache = false;
|
||||||
|
invalid_cache_generation++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,6 +111,7 @@ struct Jit::Impl {
|
||||||
jit_state.ResetRSB();
|
jit_state.ResetRSB();
|
||||||
emitter.InvalidateCacheRanges(invalid_cache_ranges);
|
emitter.InvalidateCacheRanges(invalid_cache_ranges);
|
||||||
invalid_cache_ranges.clear();
|
invalid_cache_ranges.clear();
|
||||||
|
invalid_cache_generation++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RequestCacheInvalidation() {
|
void RequestCacheInvalidation() {
|
||||||
|
@ -221,6 +225,91 @@ void Jit::SetFpscr(u32 value) {
|
||||||
return impl->jit_state.SetFpscr(value);
|
return impl->jit_state.SetFpscr(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Context Jit::SaveContext() const {
|
||||||
|
Context ctx;
|
||||||
|
SaveContext(ctx);
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Context::Impl {
|
||||||
|
JitState jit_state;
|
||||||
|
size_t invalid_cache_generation;
|
||||||
|
};
|
||||||
|
|
||||||
|
Context::Context() : impl(std::make_unique<Context::Impl>()) { impl->jit_state.ResetRSB(); }
|
||||||
|
Context::~Context() = default;
|
||||||
|
Context::Context(const Context& ctx) : impl(std::make_unique<Context::Impl>(*ctx.impl)) {}
|
||||||
|
Context::Context(Context&& ctx) : impl(std::move(ctx.impl)) {}
|
||||||
|
Context& Context::operator=(const Context& ctx) {
|
||||||
|
*impl = *ctx.impl;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Context& Context::operator=(Context&& ctx) {
|
||||||
|
impl = std::move(ctx.impl);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<std::uint32_t, 16>& Context::Regs() {
|
||||||
|
return impl->jit_state.Reg;
|
||||||
|
}
|
||||||
|
const std::array<std::uint32_t, 16>& Context::Regs() const {
|
||||||
|
return impl->jit_state.Reg;
|
||||||
|
}
|
||||||
|
std::array<std::uint32_t, 64>& Context::ExtRegs() {
|
||||||
|
return impl->jit_state.ExtReg;
|
||||||
|
}
|
||||||
|
const std::array<std::uint32_t, 64>& Context::ExtRegs() const {
|
||||||
|
return impl->jit_state.ExtReg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// View and modify CPSR.
|
||||||
|
std::uint32_t Context::Cpsr() const {
|
||||||
|
return impl->jit_state.Cpsr();
|
||||||
|
}
|
||||||
|
void Context::SetCpsr(std::uint32_t value) {
|
||||||
|
impl->jit_state.SetCpsr(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// View and modify FPSCR.
|
||||||
|
std::uint32_t Context::Fpscr() const {
|
||||||
|
return impl->jit_state.Fpscr();
|
||||||
|
}
|
||||||
|
void Context::SetFpscr(std::uint32_t value) {
|
||||||
|
return impl->jit_state.SetFpscr(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransferJitState(JitState& dest, const JitState& src, bool reset_rsb) {
|
||||||
|
dest.CPSR_ge = src.CPSR_ge;
|
||||||
|
dest.CPSR_et = src.CPSR_et;
|
||||||
|
dest.CPSR_q = src.CPSR_q;
|
||||||
|
dest.CPSR_nzcv = src.CPSR_nzcv;
|
||||||
|
dest.CPSR_jaifm = src.CPSR_jaifm;
|
||||||
|
dest.Reg = src.Reg;
|
||||||
|
dest.ExtReg = src.ExtReg;
|
||||||
|
dest.guest_MXCSR = src.guest_MXCSR;
|
||||||
|
dest.FPSCR_IDC = src.FPSCR_IDC;
|
||||||
|
dest.FPSCR_UFC = src.FPSCR_UFC;
|
||||||
|
dest.FPSCR_mode = src.FPSCR_mode;
|
||||||
|
dest.FPSCR_nzcv = src.FPSCR_nzcv;
|
||||||
|
if (reset_rsb) {
|
||||||
|
dest.ResetRSB();
|
||||||
|
} else {
|
||||||
|
dest.rsb_ptr = src.rsb_ptr;
|
||||||
|
dest.rsb_location_descriptors = src.rsb_location_descriptors;
|
||||||
|
dest.rsb_codeptrs = src.rsb_codeptrs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Jit::SaveContext(Context& ctx) const {
|
||||||
|
TransferJitState(ctx.impl->jit_state, impl->jit_state, false);
|
||||||
|
ctx.impl->invalid_cache_generation = impl->invalid_cache_generation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Jit::LoadContext(const Context& ctx) {
|
||||||
|
bool reset_rsb = ctx.impl->invalid_cache_generation != impl->invalid_cache_generation;
|
||||||
|
TransferJitState(impl->jit_state, ctx.impl->jit_state, reset_rsb);
|
||||||
|
}
|
||||||
|
|
||||||
std::string Jit::Disassemble(const IR::LocationDescriptor& descriptor) {
|
std::string Jit::Disassemble(const IR::LocationDescriptor& descriptor) {
|
||||||
return impl->Disassemble(descriptor);
|
return impl->Disassemble(descriptor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -682,7 +682,7 @@ struct ThumbTranslatorVisitor final {
|
||||||
ir.LoadWritePC(data);
|
ir.LoadWritePC(data);
|
||||||
address = ir.Add(address, ir.Imm32(4));
|
address = ir.Add(address, ir.Imm32(4));
|
||||||
ir.SetRegister(Reg::SP, address);
|
ir.SetRegister(Reg::SP, address);
|
||||||
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
ir.SetTerm(IR::Term::PopRSBHint{});
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
ir.SetRegister(Reg::SP, address);
|
ir.SetRegister(Reg::SP, address);
|
||||||
|
|
Loading…
Reference in a new issue