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 {
|
||||
|
||||
struct Context;
|
||||
|
||||
namespace IR {
|
||||
class LocationDescriptor;
|
||||
}
|
||||
|
@ -70,6 +72,10 @@ public:
|
|||
std::uint32_t Fpscr() const;
|
||||
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.
|
||||
* i.e.: We're in a callback.
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/scope_exit.h"
|
||||
#include "dynarmic/context.h"
|
||||
#include "dynarmic/dynarmic.h"
|
||||
#include "frontend/ir/basic_block.h"
|
||||
#include "frontend/ir/location_descriptor.h"
|
||||
|
@ -45,6 +46,7 @@ struct Jit::Impl {
|
|||
const UserCallbacks callbacks;
|
||||
|
||||
// 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;
|
||||
bool invalidate_entire_cache = false;
|
||||
|
||||
|
@ -98,6 +100,7 @@ struct Jit::Impl {
|
|||
|
||||
invalid_cache_ranges.clear();
|
||||
invalidate_entire_cache = false;
|
||||
invalid_cache_generation++;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -108,6 +111,7 @@ struct Jit::Impl {
|
|||
jit_state.ResetRSB();
|
||||
emitter.InvalidateCacheRanges(invalid_cache_ranges);
|
||||
invalid_cache_ranges.clear();
|
||||
invalid_cache_generation++;
|
||||
}
|
||||
|
||||
void RequestCacheInvalidation() {
|
||||
|
@ -221,6 +225,91 @@ void Jit::SetFpscr(u32 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) {
|
||||
return impl->Disassemble(descriptor);
|
||||
}
|
||||
|
|
|
@ -682,7 +682,7 @@ struct ThumbTranslatorVisitor final {
|
|||
ir.LoadWritePC(data);
|
||||
address = ir.Add(address, ir.Imm32(4));
|
||||
ir.SetRegister(Reg::SP, address);
|
||||
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||
ir.SetTerm(IR::Term::PopRSBHint{});
|
||||
return false;
|
||||
} else {
|
||||
ir.SetRegister(Reg::SP, address);
|
||||
|
|
Loading…
Reference in a new issue