mirror of
https://git.suyu.dev/suyu/dynarmic
synced 2024-11-21 14:29:03 -07:00
backend/rv64: Rework on pointer types
This commit is contained in:
parent
d743fe8a2a
commit
c90c4d48d2
7 changed files with 88 additions and 49 deletions
|
@ -314,7 +314,7 @@ void ExceptionHandler::Register(oaknut::CodeBlock& mem, std::size_t size) {
|
|||
}
|
||||
#elif defined(MCL_ARCHITECTURE_RISCV)
|
||||
void ExceptionHandler::Register(RV64::CodeBlock& mem, std::size_t size) {
|
||||
const u64 code_begin = mcl::bit_cast<u64>(mem.ptr());
|
||||
const u64 code_begin = mcl::bit_cast<u64>(mem.ptr<u64>());
|
||||
const u64 code_end = code_begin + size;
|
||||
impl = std::make_unique<Impl>(code_begin, code_end);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
#include "dynarmic/backend/riscv64/a32_address_space.h"
|
||||
|
||||
#include <mcl/assert.hpp>
|
||||
|
||||
#include "dynarmic/backend/riscv64/emit_riscv64.h"
|
||||
#include "dynarmic/frontend/A32/a32_location_descriptor.h"
|
||||
#include "dynarmic/frontend/A32/translate/a32_translate.h"
|
||||
|
@ -15,7 +17,7 @@ namespace Dynarmic::Backend::RV64 {
|
|||
A32AddressSpace::A32AddressSpace(const A32::UserConfig& conf)
|
||||
: conf(conf)
|
||||
, cb(conf.code_cache_size)
|
||||
, as(cb.ptr(), conf.code_cache_size) {
|
||||
, as(cb.ptr<u8*>(), conf.code_cache_size) {
|
||||
EmitPrelude();
|
||||
}
|
||||
|
||||
|
@ -37,15 +39,15 @@ IR::Block A32AddressSpace::GenerateIR(IR::LocationDescriptor descriptor) const {
|
|||
return ir_block;
|
||||
}
|
||||
|
||||
void* A32AddressSpace::Get(IR::LocationDescriptor descriptor) {
|
||||
CodePtr A32AddressSpace::Get(IR::LocationDescriptor descriptor) {
|
||||
if (const auto iter = block_entries.find(descriptor.Value()); iter != block_entries.end()) {
|
||||
return iter->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* A32AddressSpace::GetOrEmit(IR::LocationDescriptor descriptor) {
|
||||
if (void* block_entry = Get(descriptor)) {
|
||||
CodePtr A32AddressSpace::GetOrEmit(IR::LocationDescriptor descriptor) {
|
||||
if (CodePtr block_entry = Get(descriptor)) {
|
||||
return block_entry;
|
||||
}
|
||||
|
||||
|
@ -60,43 +62,49 @@ void* A32AddressSpace::GetOrEmit(IR::LocationDescriptor descriptor) {
|
|||
void A32AddressSpace::ClearCache() {
|
||||
block_entries.clear();
|
||||
block_infos.clear();
|
||||
as.RewindBuffer(reinterpret_cast<char*>(prelude_info.end_of_prelude) - reinterpret_cast<char*>(as.GetBufferPointer(0)));
|
||||
SetCursorPtr(prelude_info.end_of_prelude);
|
||||
}
|
||||
|
||||
void A32AddressSpace::EmitPrelude() {
|
||||
using namespace biscuit;
|
||||
prelude_info.run_code = reinterpret_cast<PreludeInfo::RunCodeFuncType>(as.GetCursorPointer());
|
||||
prelude_info.run_code = GetCursorPtr<PreludeInfo::RunCodeFuncType>();
|
||||
|
||||
// TODO: Minimize this.
|
||||
as.ADDI(sp, sp, -64 * 8);
|
||||
for (std::uint32_t i = 1; i < 32; i += 1) {
|
||||
for (u32 i = 1; i < 32; i += 1) {
|
||||
if (GPR{i} == sp || GPR{i} == tp)
|
||||
continue;
|
||||
as.SD(GPR{i}, i * 8, sp);
|
||||
}
|
||||
for (std::uint32_t i = 0; i < 32; i += 1) {
|
||||
for (u32 i = 0; i < 32; i += 1) {
|
||||
as.FSD(FPR{i}, 32 + i * 8, sp);
|
||||
}
|
||||
|
||||
as.JALR(x0, 0, a0);
|
||||
|
||||
prelude_info.return_from_run_code = reinterpret_cast<void*>(as.GetCursorPointer());
|
||||
for (std::uint32_t i = 1; i < 32; i += 1) {
|
||||
prelude_info.return_from_run_code = GetCursorPtr<CodePtr>();
|
||||
for (u32 i = 1; i < 32; i += 1) {
|
||||
if (GPR{i} == sp || GPR{i} == tp)
|
||||
continue;
|
||||
as.LD(GPR{i}, i * 8, sp);
|
||||
}
|
||||
for (std::uint32_t i = 0; i < 32; i += 1) {
|
||||
for (u32 i = 0; i < 32; i += 1) {
|
||||
as.FLD(FPR{i}, 32 + i * 8, sp);
|
||||
}
|
||||
as.ADDI(sp, sp, 64 * 8);
|
||||
as.JALR(ra);
|
||||
|
||||
prelude_info.end_of_prelude = reinterpret_cast<u32*>(as.GetCursorPointer());
|
||||
prelude_info.end_of_prelude = GetCursorPtr<CodePtr>();
|
||||
}
|
||||
|
||||
void A32AddressSpace::SetCursorPtr(CodePtr ptr) {
|
||||
ptrdiff_t offset = ptr - GetMemPtr<CodePtr>();
|
||||
ASSERT(offset >= 0);
|
||||
as.RewindBuffer(offset);
|
||||
}
|
||||
|
||||
size_t A32AddressSpace::GetRemainingSize() {
|
||||
return conf.code_cache_size - (reinterpret_cast<uintptr_t>(as.GetCursorPointer()) - reinterpret_cast<uintptr_t>(as.GetBufferPointer(0)));
|
||||
return conf.code_cache_size - (GetCursorPtr<sptr>() - GetMemPtr<sptr>());
|
||||
}
|
||||
|
||||
EmittedBlockInfo A32AddressSpace::Emit(IR::Block block) {
|
||||
|
@ -113,11 +121,11 @@ EmittedBlockInfo A32AddressSpace::Emit(IR::Block block) {
|
|||
void A32AddressSpace::Link(EmittedBlockInfo& block_info) {
|
||||
using namespace biscuit;
|
||||
for (auto [ptr_offset, target] : block_info.relocations) {
|
||||
Assembler a(reinterpret_cast<u8*>(reinterpret_cast<char*>(block_info.entry_point) + ptr_offset), 4);
|
||||
Assembler a(reinterpret_cast<u8*>(block_info.entry_point) + ptr_offset, 4);
|
||||
|
||||
switch (target) {
|
||||
case LinkTarget::ReturnFromRunCode: {
|
||||
std::ptrdiff_t off = reinterpret_cast<char*>(prelude_info.return_from_run_code) - reinterpret_cast<char*>(a.GetCursorPointer());
|
||||
std::ptrdiff_t off = prelude_info.return_from_run_code - GetCursorPtr<CodePtr>();
|
||||
a.JAL(x0, off);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -25,9 +25,9 @@ public:
|
|||
|
||||
IR::Block GenerateIR(IR::LocationDescriptor) const;
|
||||
|
||||
void* Get(IR::LocationDescriptor descriptor);
|
||||
CodePtr Get(IR::LocationDescriptor descriptor);
|
||||
|
||||
void* GetOrEmit(IR::LocationDescriptor descriptor);
|
||||
CodePtr GetOrEmit(IR::LocationDescriptor descriptor);
|
||||
|
||||
void ClearCache();
|
||||
|
||||
|
@ -36,6 +36,32 @@ private:
|
|||
|
||||
void EmitPrelude();
|
||||
|
||||
template<typename T>
|
||||
T GetMemPtr() {
|
||||
static_assert(std::is_pointer_v<T> || std::is_same_v<T, uptr> || std::is_same_v<T, sptr>);
|
||||
return reinterpret_cast<T>(as.GetBufferPointer(0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T GetMemPtr() const {
|
||||
static_assert(std::is_pointer_v<T> || std::is_same_v<T, uptr> || std::is_same_v<T, sptr>);
|
||||
return reinterpret_cast<const T>(as.GetBufferPointer(0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T GetCursorPtr() {
|
||||
static_assert(std::is_pointer_v<T> || std::is_same_v<T, uptr> || std::is_same_v<T, sptr>);
|
||||
return reinterpret_cast<T>(as.GetCursorPointer());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T GetCursorPtr() const {
|
||||
static_assert(std::is_pointer_v<T> || std::is_same_v<T, uptr> || std::is_same_v<T, sptr>);
|
||||
return reinterpret_cast<const T>(as.GetCursorPointer());
|
||||
}
|
||||
|
||||
void SetCursorPtr(CodePtr ptr);
|
||||
|
||||
size_t GetRemainingSize();
|
||||
EmittedBlockInfo Emit(IR::Block ir_block);
|
||||
void Link(EmittedBlockInfo& block);
|
||||
|
@ -45,15 +71,15 @@ private:
|
|||
CodeBlock cb;
|
||||
biscuit::Assembler as;
|
||||
|
||||
tsl::robin_map<u64, void*> block_entries;
|
||||
tsl::robin_map<u64, CodePtr> block_entries;
|
||||
tsl::robin_map<u64, EmittedBlockInfo> block_infos;
|
||||
|
||||
struct PreludeInfo {
|
||||
u32* end_of_prelude;
|
||||
CodePtr end_of_prelude;
|
||||
|
||||
using RunCodeFuncType = HaltReason (*)(void* entry_point, A32JitState* context, volatile u32* halt_reason);
|
||||
using RunCodeFuncType = HaltReason (*)(CodePtr entry_point, A32JitState* context, volatile u32* halt_reason);
|
||||
RunCodeFuncType run_code;
|
||||
void* return_from_run_code;
|
||||
CodePtr return_from_run_code;
|
||||
} prelude_info;
|
||||
};
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ struct Jit::Impl final {
|
|||
HaltExecution(HaltReason::CacheInvalidation);
|
||||
}
|
||||
|
||||
void InvalidateCacheRange(std::uint32_t start_address, std::size_t length) {
|
||||
void InvalidateCacheRange(u32 start_address, size_t length) {
|
||||
std::unique_lock lock{invalidation_mutex};
|
||||
invalid_cache_ranges.add(boost::icl::discrete_interval<u32>::closed(start_address, static_cast<u32>(start_address + length - 1)));
|
||||
HaltExecution(HaltReason::CacheInvalidation);
|
||||
|
@ -80,35 +80,35 @@ struct Jit::Impl final {
|
|||
Atomic::And(&halt_reason, ~static_cast<u32>(hr));
|
||||
}
|
||||
|
||||
std::array<std::uint32_t, 16>& Regs() {
|
||||
std::array<u32, 16>& Regs() {
|
||||
return current_state.regs;
|
||||
}
|
||||
|
||||
const std::array<std::uint32_t, 16>& Regs() const {
|
||||
const std::array<u32, 16>& Regs() const {
|
||||
return current_state.regs;
|
||||
}
|
||||
|
||||
std::array<std::uint32_t, 64>& ExtRegs() {
|
||||
std::array<u32, 64>& ExtRegs() {
|
||||
return current_state.ext_regs;
|
||||
}
|
||||
|
||||
const std::array<std::uint32_t, 64>& ExtRegs() const {
|
||||
const std::array<u32, 64>& ExtRegs() const {
|
||||
return current_state.ext_regs;
|
||||
}
|
||||
|
||||
std::uint32_t Cpsr() const {
|
||||
u32 Cpsr() const {
|
||||
return current_state.Cpsr();
|
||||
}
|
||||
|
||||
void SetCpsr(std::uint32_t value) {
|
||||
void SetCpsr(u32 value) {
|
||||
current_state.SetCpsr(value);
|
||||
}
|
||||
|
||||
std::uint32_t Fpscr() const {
|
||||
u32 Fpscr() const {
|
||||
return current_state.Fpscr();
|
||||
}
|
||||
|
||||
void SetFpscr(std::uint32_t value) {
|
||||
void SetFpscr(u32 value) {
|
||||
current_state.SetFpscr(value);
|
||||
}
|
||||
|
||||
|
@ -158,7 +158,7 @@ void Jit::ClearCache() {
|
|||
impl->ClearCache();
|
||||
}
|
||||
|
||||
void Jit::InvalidateCacheRange(std::uint32_t start_address, std::size_t length) {
|
||||
void Jit::InvalidateCacheRange(u32 start_address, std::size_t length) {
|
||||
impl->InvalidateCacheRange(start_address, length);
|
||||
}
|
||||
|
||||
|
@ -174,35 +174,35 @@ void Jit::ClearHalt(HaltReason hr) {
|
|||
impl->ClearHalt(hr);
|
||||
}
|
||||
|
||||
std::array<std::uint32_t, 16>& Jit::Regs() {
|
||||
std::array<u32, 16>& Jit::Regs() {
|
||||
return impl->Regs();
|
||||
}
|
||||
|
||||
const std::array<std::uint32_t, 16>& Jit::Regs() const {
|
||||
const std::array<u32, 16>& Jit::Regs() const {
|
||||
return impl->Regs();
|
||||
}
|
||||
|
||||
std::array<std::uint32_t, 64>& Jit::ExtRegs() {
|
||||
std::array<u32, 64>& Jit::ExtRegs() {
|
||||
return impl->ExtRegs();
|
||||
}
|
||||
|
||||
const std::array<std::uint32_t, 64>& Jit::ExtRegs() const {
|
||||
const std::array<u32, 64>& Jit::ExtRegs() const {
|
||||
return impl->ExtRegs();
|
||||
}
|
||||
|
||||
std::uint32_t Jit::Cpsr() const {
|
||||
u32 Jit::Cpsr() const {
|
||||
return impl->Cpsr();
|
||||
}
|
||||
|
||||
void Jit::SetCpsr(std::uint32_t value) {
|
||||
void Jit::SetCpsr(u32 value) {
|
||||
impl->SetCpsr(value);
|
||||
}
|
||||
|
||||
std::uint32_t Jit::Fpscr() const {
|
||||
u32 Jit::Fpscr() const {
|
||||
return impl->Fpscr();
|
||||
}
|
||||
|
||||
void Jit::SetFpscr(std::uint32_t value) {
|
||||
void Jit::SetFpscr(u32 value) {
|
||||
impl->SetFpscr(value);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ class CodeBlock {
|
|||
public:
|
||||
explicit CodeBlock(std::size_t size)
|
||||
: memsize(size) {
|
||||
mem = (std::uint8_t*)mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
mem = (u8*)mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
|
||||
if (mem == nullptr)
|
||||
throw std::bad_alloc{};
|
||||
|
@ -29,12 +29,14 @@ public:
|
|||
munmap(mem, memsize);
|
||||
}
|
||||
|
||||
std::uint8_t* ptr() const {
|
||||
return mem;
|
||||
template<typename T>
|
||||
T ptr() const {
|
||||
static_assert(std::is_pointer_v<T> || std::is_same_v<T, uptr> || std::is_same_v<T, sptr>);
|
||||
return reinterpret_cast<T>(mem);
|
||||
}
|
||||
|
||||
protected:
|
||||
std::uint8_t* mem;
|
||||
std::size_t memsize = 0;
|
||||
u8* mem;
|
||||
size_t memsize = 0;
|
||||
};
|
||||
} // namespace Dynarmic::Backend::RV64
|
||||
|
|
|
@ -16,7 +16,7 @@ EmittedBlockInfo EmitRV64(biscuit::Assembler& as, [[maybe_unused]] IR::Block blo
|
|||
using namespace biscuit;
|
||||
|
||||
EmittedBlockInfo ebi;
|
||||
ebi.entry_point = reinterpret_cast<void*>(as.GetCursorPointer());
|
||||
ebi.entry_point = reinterpret_cast<CodePtr>(as.GetCursorPointer());
|
||||
|
||||
as.ADDIW(a0, zero, 8);
|
||||
as.SW(a0, offsetof(A32JitState, regs) + 0 * sizeof(u32), a1);
|
||||
|
@ -25,10 +25,11 @@ EmittedBlockInfo EmitRV64(biscuit::Assembler& as, [[maybe_unused]] IR::Block blo
|
|||
as.SW(a0, offsetof(A32JitState, regs) + 1 * sizeof(u32), a1);
|
||||
as.SW(a0, offsetof(A32JitState, regs) + 15 * sizeof(u32), a1);
|
||||
|
||||
ebi.relocations[reinterpret_cast<char*>(as.GetCursorPointer()) - reinterpret_cast<char*>(ebi.entry_point)] = LinkTarget::ReturnFromRunCode;
|
||||
ptrdiff_t offset = reinterpret_cast<CodePtr>(as.GetCursorPointer()) - ebi.entry_point;
|
||||
ebi.relocations[offset] = LinkTarget::ReturnFromRunCode;
|
||||
as.NOP();
|
||||
|
||||
ebi.size = reinterpret_cast<size_t>(as.GetCursorPointer()) - reinterpret_cast<size_t>(ebi.entry_point);
|
||||
ebi.size = reinterpret_cast<CodePtr>(as.GetCursorPointer()) - ebi.entry_point;
|
||||
return ebi;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,12 +18,14 @@ class Block;
|
|||
|
||||
namespace Dynarmic::Backend::RV64 {
|
||||
|
||||
using CodePtr = std::byte*;
|
||||
|
||||
enum class LinkTarget {
|
||||
ReturnFromRunCode,
|
||||
};
|
||||
|
||||
struct EmittedBlockInfo {
|
||||
void* entry_point;
|
||||
CodePtr entry_point;
|
||||
size_t size;
|
||||
tsl::robin_map<std::ptrdiff_t, LinkTarget> relocations;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue