diff --git a/src/dynarmic/backend/exception_handler_posix.cpp b/src/dynarmic/backend/exception_handler_posix.cpp index 5b442196..2d6d6ea6 100644 --- a/src/dynarmic/backend/exception_handler_posix.cpp +++ b/src/dynarmic/backend/exception_handler_posix.cpp @@ -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(mem.ptr()); + const u64 code_begin = mcl::bit_cast(mem.ptr()); const u64 code_end = code_begin + size; impl = std::make_unique(code_begin, code_end); } diff --git a/src/dynarmic/backend/riscv64/a32_address_space.cpp b/src/dynarmic/backend/riscv64/a32_address_space.cpp index c8b7ca2d..868503f1 100644 --- a/src/dynarmic/backend/riscv64/a32_address_space.cpp +++ b/src/dynarmic/backend/riscv64/a32_address_space.cpp @@ -5,6 +5,8 @@ #include "dynarmic/backend/riscv64/a32_address_space.h" +#include + #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(), 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(prelude_info.end_of_prelude) - reinterpret_cast(as.GetBufferPointer(0))); + SetCursorPtr(prelude_info.end_of_prelude); } void A32AddressSpace::EmitPrelude() { using namespace biscuit; - prelude_info.run_code = reinterpret_cast(as.GetCursorPointer()); + prelude_info.run_code = GetCursorPtr(); // 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(as.GetCursorPointer()); - for (std::uint32_t i = 1; i < 32; i += 1) { + prelude_info.return_from_run_code = GetCursorPtr(); + 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(as.GetCursorPointer()); + prelude_info.end_of_prelude = GetCursorPtr(); +} + +void A32AddressSpace::SetCursorPtr(CodePtr ptr) { + ptrdiff_t offset = ptr - GetMemPtr(); + ASSERT(offset >= 0); + as.RewindBuffer(offset); } size_t A32AddressSpace::GetRemainingSize() { - return conf.code_cache_size - (reinterpret_cast(as.GetCursorPointer()) - reinterpret_cast(as.GetBufferPointer(0))); + return conf.code_cache_size - (GetCursorPtr() - GetMemPtr()); } 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(reinterpret_cast(block_info.entry_point) + ptr_offset), 4); + Assembler a(reinterpret_cast(block_info.entry_point) + ptr_offset, 4); switch (target) { case LinkTarget::ReturnFromRunCode: { - std::ptrdiff_t off = reinterpret_cast(prelude_info.return_from_run_code) - reinterpret_cast(a.GetCursorPointer()); + std::ptrdiff_t off = prelude_info.return_from_run_code - GetCursorPtr(); a.JAL(x0, off); break; } diff --git a/src/dynarmic/backend/riscv64/a32_address_space.h b/src/dynarmic/backend/riscv64/a32_address_space.h index 1061c0ed..628f72c2 100644 --- a/src/dynarmic/backend/riscv64/a32_address_space.h +++ b/src/dynarmic/backend/riscv64/a32_address_space.h @@ -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 + T GetMemPtr() { + static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); + return reinterpret_cast(as.GetBufferPointer(0)); + } + + template + T GetMemPtr() const { + static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); + return reinterpret_cast(as.GetBufferPointer(0)); + } + + template + T GetCursorPtr() { + static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); + return reinterpret_cast(as.GetCursorPointer()); + } + + template + T GetCursorPtr() const { + static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); + return reinterpret_cast(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 block_entries; + tsl::robin_map block_entries; tsl::robin_map 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; }; diff --git a/src/dynarmic/backend/riscv64/a32_interface.cpp b/src/dynarmic/backend/riscv64/a32_interface.cpp index 5cd10eed..02aabb33 100644 --- a/src/dynarmic/backend/riscv64/a32_interface.cpp +++ b/src/dynarmic/backend/riscv64/a32_interface.cpp @@ -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::closed(start_address, static_cast(start_address + length - 1))); HaltExecution(HaltReason::CacheInvalidation); @@ -80,35 +80,35 @@ struct Jit::Impl final { Atomic::And(&halt_reason, ~static_cast(hr)); } - std::array& Regs() { + std::array& Regs() { return current_state.regs; } - const std::array& Regs() const { + const std::array& Regs() const { return current_state.regs; } - std::array& ExtRegs() { + std::array& ExtRegs() { return current_state.ext_regs; } - const std::array& ExtRegs() const { + const std::array& 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& Jit::Regs() { +std::array& Jit::Regs() { return impl->Regs(); } -const std::array& Jit::Regs() const { +const std::array& Jit::Regs() const { return impl->Regs(); } -std::array& Jit::ExtRegs() { +std::array& Jit::ExtRegs() { return impl->ExtRegs(); } -const std::array& Jit::ExtRegs() const { +const std::array& 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); } diff --git a/src/dynarmic/backend/riscv64/code_block.h b/src/dynarmic/backend/riscv64/code_block.h index c41b9a47..6ac014a5 100644 --- a/src/dynarmic/backend/riscv64/code_block.h +++ b/src/dynarmic/backend/riscv64/code_block.h @@ -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 + T ptr() const { + static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); + return reinterpret_cast(mem); } protected: - std::uint8_t* mem; - std::size_t memsize = 0; + u8* mem; + size_t memsize = 0; }; } // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/backend/riscv64/emit_riscv64.cpp b/src/dynarmic/backend/riscv64/emit_riscv64.cpp index aba44243..0fe3e8e0 100644 --- a/src/dynarmic/backend/riscv64/emit_riscv64.cpp +++ b/src/dynarmic/backend/riscv64/emit_riscv64.cpp @@ -16,7 +16,7 @@ EmittedBlockInfo EmitRV64(biscuit::Assembler& as, [[maybe_unused]] IR::Block blo using namespace biscuit; EmittedBlockInfo ebi; - ebi.entry_point = reinterpret_cast(as.GetCursorPointer()); + ebi.entry_point = reinterpret_cast(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(as.GetCursorPointer()) - reinterpret_cast(ebi.entry_point)] = LinkTarget::ReturnFromRunCode; + ptrdiff_t offset = reinterpret_cast(as.GetCursorPointer()) - ebi.entry_point; + ebi.relocations[offset] = LinkTarget::ReturnFromRunCode; as.NOP(); - ebi.size = reinterpret_cast(as.GetCursorPointer()) - reinterpret_cast(ebi.entry_point); + ebi.size = reinterpret_cast(as.GetCursorPointer()) - ebi.entry_point; return ebi; } diff --git a/src/dynarmic/backend/riscv64/emit_riscv64.h b/src/dynarmic/backend/riscv64/emit_riscv64.h index 7f88586c..8ea58418 100644 --- a/src/dynarmic/backend/riscv64/emit_riscv64.h +++ b/src/dynarmic/backend/riscv64/emit_riscv64.h @@ -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 relocations; };