interface: Allow saving and storing of contexts

This commit is contained in:
MerryMage 2017-12-03 18:25:40 +00:00
parent 19a7fb8992
commit 4393473d06
4 changed files with 140 additions and 1 deletions

View 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

View file

@ -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.

View file

@ -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);
} }

View file

@ -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);