A64: Backend framework

This commit is contained in:
MerryMage 2018-01-06 21:15:25 +00:00
parent e161cf16f5
commit d1eb757f93
48 changed files with 1183 additions and 90 deletions

View file

@ -0,0 +1,98 @@
/* This file is part of the dynarmic project.
* Copyright (c) 2018 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 <cstddef>
#include <cstdint>
#include <memory>
#include <dynarmic/A64/config.h>
namespace Dynarmic {
namespace A64 {
struct Context;
class Jit final {
public:
explicit Jit(UserConfig conf);
~Jit();
/**
* Runs the emulated CPU.
* Cannot be recursively called.
*/
void Run();
/**
* Clears the code cache of all compiled code.
* Can be called at any time. Halts execution if called within a callback.
*/
void ClearCache();
/**
* Invalidate the code cache at a range of addresses.
* @param start_address The starting address of the range to invalidate.
* @param length The length (in bytes) of the range to invalidate.
*/
void InvalidateCacheRange(std::uint64_t start_address, std::size_t length);
/**
* Reset CPU state to state at startup. Does not clear code cache.
* Cannot be called from a callback.
*/
void Reset();
/**
* Stops execution in Jit::Run.
* Can only be called from a callback.
*/
void HaltExecution();
/// Read Stack Pointer
std::uint64_t GetSP() const;
/// Modify Stack Pointer
void SetSP(std::uint64_t value);
/// Read Program Counter
std::uint64_t GetPC() const;
/// Modify Program Counter
void SetPC(std::uint64_t value);
/// Read general-purpose register.
std::uint64_t GetRegister(std::size_t index) const;
/// Modify general-purpose register.
void SetRegister(size_t index, std::uint64_t value);
struct Vector {
std::uint64_t low;
std::uint64_t high;
};
/// Read floating point and SIMD register.
Vector GetVector(std::size_t index) const;
/// Modify floating point and SIMD register.
void SetVector(std::size_t index, Vector value);
/// View FPCR.
std::uint32_t GetFpcr() const;
/// Modify FPCR.
void SetFpcr(std::uint32_t value);
/**
* Returns true if Jit::Run was called but hasn't returned yet.
* i.e.: We're in a callback.
*/
bool IsExecuting() const;
private:
struct Impl;
std::unique_ptr<Impl> impl;
};
} // namespace A64
} // namespace Dynarmic

View file

@ -0,0 +1,66 @@
/* This file is part of the dynarmic project.
* Copyright (c) 2018 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 <cstddef>
#include <cstdint>
#include <memory>
namespace Dynarmic {
namespace A64 {
using VAddr = std::uint64_t;
struct UserCallbacks {
virtual ~UserCallbacks() = default;
// All reads through this callback are 4-byte aligned.
// Memory must be interpreted as little endian.
virtual std::uint32_t MemoryReadCode(VAddr vaddr) { return MemoryRead32(vaddr); }
// Reads through these callbacks may not be aligned.
virtual std::uint8_t MemoryRead8(VAddr vaddr) = 0;
virtual std::uint16_t MemoryRead16(VAddr vaddr) = 0;
virtual std::uint32_t MemoryRead32(VAddr vaddr) = 0;
virtual std::uint64_t MemoryRead64(VAddr vaddr) = 0;
// Writes through these callbacks may not be aligned.
virtual void MemoryWrite8(VAddr vaddr, std::uint8_t value) = 0;
virtual void MemoryWrite16(VAddr vaddr, std::uint16_t value) = 0;
virtual void MemoryWrite32(VAddr vaddr, std::uint32_t value) = 0;
virtual void MemoryWrite64(VAddr vaddr, std::uint64_t value) = 0;
// If this callback returns true, the JIT will assume MemoryRead* callbacks will always
// return the same value at any point in time for this vaddr. The JIT may use this information
// in optimizations.
// A conservative implementation that always returns false is safe.
virtual bool IsReadOnlyMemory(VAddr /* vaddr */) { return false; }
/// The intrepreter must execute exactly num_instructions starting from PC.
virtual void InterpreterFallback(VAddr pc, size_t num_instructions) = 0;
// This callback is called whenever a SVC instruction is executed.
virtual void CallSVC(std::uint32_t swi) = 0;
// Timing-related callbacks
// ticks ticks have passed
virtual void AddTicks(std::uint64_t ticks) = 0;
// How many more ticks am I allowed to execute?
virtual std::uint64_t GetTicksRemaining() = 0;
};
struct UserConfig {
UserCallbacks* callbacks;
// Determines whether AddTicks and GetTicksRemaining are called.
// If false, execution will continue until soon after Jit::HaltExecution is called.
// bool enable_ticks = true; // TODO
};
} // namespace A64
} // namespace Dynarmic