A32: Change UserCallbacks to be similar to A64's interface

This commit is contained in:
MerryMage 2018-01-27 22:36:55 +00:00
parent b9ce660113
commit 98ec9c5f90
21 changed files with 472 additions and 622 deletions

View file

@ -11,7 +11,7 @@
#include <memory>
#include <string>
#include <dynarmic/A32/callbacks.h>
#include <dynarmic/A32/config.h>
namespace Dynarmic {
namespace IR {
@ -26,7 +26,7 @@ struct Context;
class Jit final {
public:
explicit Jit(UserCallbacks callbacks);
explicit Jit(UserConfig conf);
~Jit();
/**

View file

@ -1,71 +0,0 @@
/* 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 <cstddef>
#include <cstdint>
#include <memory>
namespace Dynarmic {
namespace A32 {
class Coprocessor;
class Jit;
/// These function pointers may be inserted into compiled code.
struct UserCallbacks {
struct Memory {
// All reads through this callback are 4-byte aligned.
// Memory must be interpreted as little endian.
std::uint32_t (*ReadCode)(std::uint32_t vaddr);
// Reads through these callbacks may not be aligned.
// Memory must be interpreted as if ENDIANSTATE == 0, endianness will be corrected by the JIT.
std::uint8_t (*Read8)(std::uint32_t vaddr);
std::uint16_t (*Read16)(std::uint32_t vaddr);
std::uint32_t (*Read32)(std::uint32_t vaddr);
std::uint64_t (*Read64)(std::uint32_t vaddr);
// Writes through these callbacks may not be aligned.
// Memory must be interpreted as if ENDIANSTATE == 0, endianness will be corrected by the JIT.
void (*Write8)(std::uint32_t vaddr, std::uint8_t value);
void (*Write16)(std::uint32_t vaddr, std::uint16_t value);
void (*Write32)(std::uint32_t vaddr, std::uint32_t value);
void (*Write64)(std::uint32_t vaddr, std::uint64_t value);
// 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.
// An conservative implementation that always returns false is safe.
bool (*IsReadOnlyMemory)(std::uint32_t vaddr);
} memory = {};
/// The intrepreter must execute only one instruction at PC.
void (*InterpreterFallback)(std::uint32_t pc, Jit* jit, void* user_arg);
void* user_arg = nullptr;
// This callback is called whenever a SVC instruction is executed.
void (*CallSVC)(std::uint32_t swi);
// Timing-related callbacks
void (*AddTicks)(std::uint64_t ticks);
std::uint64_t (*GetTicksRemaining)();
// Page Table
// The page table is used for faster memory access. If an entry in the table is nullptr,
// the JIT will fallback to calling the MemoryRead*/MemoryWrite* callbacks.
static constexpr std::size_t PAGE_BITS = 12;
static constexpr std::size_t NUM_PAGE_TABLE_ENTRIES = 1 << (32 - PAGE_BITS);
std::array<std::uint8_t*, NUM_PAGE_TABLE_ENTRIES>* page_table = nullptr;
// Coprocessors
std::array<std::shared_ptr<Coprocessor>, 16> coprocessors;
};
} // namespace A32
} // namespace Dynarmic

View file

@ -0,0 +1,86 @@
/* 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 <cstddef>
#include <cstdint>
#include <memory>
namespace Dynarmic {
namespace A32 {
using VAddr = std::uint32_t;
class Coprocessor;
enum class Exception {
/// An UndefinedFault occured due to executing instruction with an unallocated encoding
UndefinedInstruction,
/// An unpredictable instruction is to be executed. Implementation-defined behaviour should now happen.
/// This behaviour is up to the user of this library to define.
UnpredictableInstruction,
};
/// These function pointers may be inserted into compiled code.
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.
// Memory must be interpreted as if ENDIANSTATE == 0, endianness will be corrected by the JIT.
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;
virtual void ExceptionRaised(VAddr pc, Exception exception) = 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;
// Page Table
// The page table is used for faster memory access. If an entry in the table is nullptr,
// the JIT will fallback to calling the MemoryRead*/MemoryWrite* callbacks.
static constexpr std::size_t PAGE_BITS = 12;
static constexpr std::size_t NUM_PAGE_TABLE_ENTRIES = 1 << (32 - PAGE_BITS);
std::array<std::uint8_t*, NUM_PAGE_TABLE_ENTRIES>* page_table = nullptr;
// Coprocessors
std::array<std::shared_ptr<Coprocessor>, 16> coprocessors;
};
} // namespace A32
} // namespace Dynarmic