mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-05-30 23:17:09 +02:00
[dynarmic] bootstrap loongarch64 host build (#4015)
Minimal additions to make Eden compile. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4015 Reviewed-by: Lizzie <lizzie@eden-emu.dev> Reviewed-by: crueter <crueter@eden-emu.dev>
This commit is contained in:
parent
c84d605426
commit
ff7bbaea7d
15 changed files with 607 additions and 9 deletions
5
externals/CMakeLists.txt
vendored
5
externals/CMakeLists.txt
vendored
|
|
@ -82,6 +82,11 @@ if (ARCHITECTURE_riscv64)
|
|||
AddJsonPackage(biscuit)
|
||||
endif()
|
||||
|
||||
# Lagoon
|
||||
if (ARCHITECTURE_loongarch64)
|
||||
AddJsonPackage(lagoon)
|
||||
endif()
|
||||
|
||||
# Vulkan stuff
|
||||
AddDependentPackages(vulkan-headers vulkan-utility-libraries)
|
||||
|
||||
|
|
|
|||
6
externals/cpmfile.json
vendored
6
externals/cpmfile.json
vendored
|
|
@ -67,6 +67,12 @@
|
|||
"tag": "v%VERSION%",
|
||||
"hash": "9697e80a7d5d9bcb3ce51051a9a24962fb90ca79d215f1f03ae6b58da8ba13a63b5dda1b4dde3d26ac6445029696b8ef2883f4e5a777b342bba01283ed293856"
|
||||
},
|
||||
"lagoon": {
|
||||
"repo": "loongson-community/lagoon",
|
||||
"tag": "%VERSION%",
|
||||
"version": "1.0.0",
|
||||
"hash": "b9380f99c6effaeccc6d8f81d4942e852c11ad28613df637e155451556ae5826f93765bee57a5c87a9740d2bd1db463ad0f55a947772fe9d57eeabae3efa373e"
|
||||
},
|
||||
"libadrenotools": {
|
||||
"repo": "eden-emulator/libadrenotools",
|
||||
"sha": "8ba23b42d7",
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
include_directories(.)
|
||||
|
||||
# Dynarmic
|
||||
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64) AND NOT YUZU_STATIC_ROOM)
|
||||
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_loongarch64) AND NOT YUZU_STATIC_ROOM)
|
||||
add_subdirectory(dynarmic)
|
||||
add_library(dynarmic::dynarmic ALIAS dynarmic)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -1246,7 +1246,7 @@ if (HAS_NCE)
|
|||
target_link_libraries(core PRIVATE merry::oaknut)
|
||||
endif()
|
||||
|
||||
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64)
|
||||
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_loongarch64)
|
||||
target_sources(core PRIVATE
|
||||
arm/dynarmic/arm_dynarmic.h
|
||||
arm/dynarmic/arm_dynarmic_64.cpp
|
||||
|
|
|
|||
|
|
@ -130,6 +130,10 @@ if ("riscv64" IN_LIST ARCHITECTURE)
|
|||
find_package(biscuit 0.9.1 REQUIRED)
|
||||
endif()
|
||||
|
||||
if ("loongarch64" IN_LIST ARCHITECTURE)
|
||||
find_package(lagoon REQUIRED)
|
||||
endif()
|
||||
|
||||
if ("x86_64" IN_LIST ARCHITECTURE)
|
||||
find_package(xbyak 7 CONFIG)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -295,6 +295,20 @@ if ("riscv64" IN_LIST ARCHITECTURE)
|
|||
message(WARNING "TODO: Incomplete frontend for this host architecture")
|
||||
endif()
|
||||
|
||||
if ("loongarch64" IN_LIST ARCHITECTURE)
|
||||
target_link_libraries(dynarmic PRIVATE lagoon::lagoon)
|
||||
|
||||
target_sources(dynarmic PRIVATE
|
||||
backend/loongarch64/exclusive_monitor.cpp
|
||||
backend/loongarch64/a32_interface.cpp
|
||||
backend/loongarch64/a64_interface.cpp
|
||||
backend/loongarch64/code_block.h
|
||||
|
||||
common/spin_lock_loongarch64.cpp
|
||||
)
|
||||
message(WARNING "TODO: Incomplete frontend for this host architecture")
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
target_sources(dynarmic PRIVATE backend/exception_handler_windows.cpp)
|
||||
elseif (APPLE)
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@ class CodeBlock;
|
|||
namespace Dynarmic::Backend::RV64 {
|
||||
class CodeBlock;
|
||||
} // namespace Dynarmic::Backend::RV64
|
||||
#elif defined(ARCHITECTURE_loongarch64)
|
||||
namespace Dynarmic::Backend::LoongArch64 {
|
||||
class CodeBlock;
|
||||
} // namespace Dynarmic::Backend::LoongArch64
|
||||
#else
|
||||
# error "Invalid architecture"
|
||||
#endif
|
||||
|
|
@ -45,6 +49,10 @@ struct FakeCall {
|
|||
struct FakeCall {
|
||||
u64 call_sepc;
|
||||
};
|
||||
#elif defined(ARCHITECTURE_loongarch64)
|
||||
struct FakeCall {
|
||||
u64 call_pc;
|
||||
};
|
||||
#else
|
||||
# error "Invalid architecture"
|
||||
#endif
|
||||
|
|
@ -60,6 +68,8 @@ public:
|
|||
void Register(oaknut::CodeBlock& mem, std::size_t mem_size);
|
||||
#elif defined(ARCHITECTURE_riscv64)
|
||||
void Register(RV64::CodeBlock& mem, std::size_t mem_size);
|
||||
#elif defined(ARCHITECTURE_loongarch64)
|
||||
void Register(LoongArch64::CodeBlock& mem, std::size_t mem_size);
|
||||
#else
|
||||
# error "Invalid architecture"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
|
|
@ -28,6 +28,10 @@ void ExceptionHandler::Register(oaknut::CodeBlock&, std::size_t) {
|
|||
void ExceptionHandler::Register(RV64::CodeBlock&, std::size_t) {
|
||||
// Do nothing
|
||||
}
|
||||
#elif defined(ARCHITECTURE_loongarch64)
|
||||
void ExceptionHandler::Register(LoongArch64::CodeBlock&, std::size_t) {
|
||||
// Do nothing
|
||||
}
|
||||
#else
|
||||
# error "Invalid architecture"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -6,20 +6,25 @@
|
|||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <bit>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include <optional>
|
||||
#include <bit>
|
||||
#include <fmt/format.h>
|
||||
#include <shared_mutex>
|
||||
|
||||
#include <ankerl/unordered_dense.h>
|
||||
#include "dynarmic/backend/exception_handler.h"
|
||||
#include <fmt/format.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "dynarmic/common/context.h"
|
||||
#include "common/common_types.h"
|
||||
#include "dynarmic/backend/exception_handler.h"
|
||||
#include "dynarmic/common/context.h"
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
# include "dynarmic/backend/x64/block_of_code.h"
|
||||
#elif defined(ARCHITECTURE_arm64)
|
||||
|
|
@ -27,6 +32,8 @@
|
|||
# include "dynarmic/backend/arm64/abi.h"
|
||||
#elif defined(ARCHITECTURE_riscv64)
|
||||
# include "dynarmic/backend/riscv64/code_block.h"
|
||||
#elif defined(ARCHITECTURE_loongarch64)
|
||||
# include "dynarmic/backend/loongarch64/code_block.h"
|
||||
#else
|
||||
# error "Invalid architecture"
|
||||
#endif
|
||||
|
|
@ -150,6 +157,16 @@ void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) {
|
|||
}
|
||||
}
|
||||
fmt::print(stderr, "Unhandled {} at pc {:#018x}\n", sig == SIGSEGV ? "SIGSEGV" : "SIGBUS", CTX_SEPC);
|
||||
#elif defined(ARCHITECTURE_loongarch64)
|
||||
{
|
||||
std::shared_lock guard(sig_handler->code_block_infos_mutex);
|
||||
if (const auto iter = sig_handler->FindCodeBlockInfo(CTX_PC); iter != sig_handler->code_block_infos.end()) {
|
||||
FakeCall fc = iter->second.cb(CTX_PC);
|
||||
CTX_PC = fc.call_pc;
|
||||
return;
|
||||
}
|
||||
}
|
||||
fmt::print(stderr, "Unhandled {} at pc {:#018x}\n", sig == SIGSEGV ? "SIGSEGV" : "SIGBUS", CTX_PC);
|
||||
#else
|
||||
# error "Invalid architecture"
|
||||
#endif
|
||||
|
|
@ -209,6 +226,10 @@ void ExceptionHandler::Register(oaknut::CodeBlock& mem, std::size_t size) {
|
|||
void ExceptionHandler::Register(RV64::CodeBlock& mem, std::size_t size) {
|
||||
impl = std::make_unique<Impl>(std::bit_cast<u64>(mem.ptr<u64>()), size);
|
||||
}
|
||||
#elif defined(ARCHITECTURE_loongarch64)
|
||||
void ExceptionHandler::Register(LoongArch64::CodeBlock& mem, std::size_t size) {
|
||||
impl = std::make_unique<Impl>(std::bit_cast<u64>(mem.ptr<u64>()), size);
|
||||
}
|
||||
#else
|
||||
# error "Invalid architecture"
|
||||
#endif
|
||||
|
|
|
|||
170
src/dynarmic/src/dynarmic/backend/loongarch64/a32_interface.cpp
Normal file
170
src/dynarmic/src/dynarmic/backend/loongarch64/a32_interface.cpp
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "dynarmic/interface/A32/a32.h"
|
||||
|
||||
namespace Dynarmic::A32 {
|
||||
|
||||
struct Jit::Impl final {
|
||||
explicit Impl(UserConfig conf_) : conf(std::move(conf_)) {}
|
||||
|
||||
HaltReason Run() {
|
||||
UNIMPLEMENTED();
|
||||
return halt_reason;
|
||||
}
|
||||
|
||||
HaltReason Step() {
|
||||
UNIMPLEMENTED();
|
||||
return halt_reason | HaltReason::Step;
|
||||
}
|
||||
|
||||
void ClearCache() {
|
||||
HaltExecution(HaltReason::CacheInvalidation);
|
||||
}
|
||||
|
||||
void InvalidateCacheRange(u32, std::size_t) {
|
||||
HaltExecution(HaltReason::CacheInvalidation);
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
regs = {};
|
||||
ext_regs = {};
|
||||
cpsr = 0;
|
||||
fpscr = 0;
|
||||
halt_reason = {};
|
||||
}
|
||||
|
||||
void HaltExecution(HaltReason hr) {
|
||||
halt_reason |= hr;
|
||||
}
|
||||
|
||||
void ClearHalt(HaltReason hr) {
|
||||
halt_reason &= ~hr;
|
||||
}
|
||||
|
||||
std::array<u32, 16>& Regs() {
|
||||
return regs;
|
||||
}
|
||||
|
||||
const std::array<u32, 16>& Regs() const {
|
||||
return regs;
|
||||
}
|
||||
|
||||
std::array<u32, 64>& ExtRegs() {
|
||||
return ext_regs;
|
||||
}
|
||||
|
||||
const std::array<u32, 64>& ExtRegs() const {
|
||||
return ext_regs;
|
||||
}
|
||||
|
||||
u32 Cpsr() const {
|
||||
return cpsr;
|
||||
}
|
||||
|
||||
void SetCpsr(u32 value) {
|
||||
cpsr = value;
|
||||
}
|
||||
|
||||
u32 Fpscr() const {
|
||||
return fpscr;
|
||||
}
|
||||
|
||||
void SetFpscr(u32 value) {
|
||||
fpscr = value;
|
||||
}
|
||||
|
||||
void ClearExclusiveState() {}
|
||||
|
||||
std::string Disassemble() const {
|
||||
return {};
|
||||
}
|
||||
|
||||
UserConfig conf;
|
||||
std::array<u32, 16> regs{};
|
||||
std::array<u32, 64> ext_regs{};
|
||||
u32 cpsr = 0;
|
||||
u32 fpscr = 0;
|
||||
HaltReason halt_reason{};
|
||||
};
|
||||
|
||||
Jit::Jit(UserConfig conf) : impl(std::make_unique<Impl>(std::move(conf))) {}
|
||||
|
||||
Jit::~Jit() = default;
|
||||
|
||||
HaltReason Jit::Run() {
|
||||
return impl->Run();
|
||||
}
|
||||
|
||||
HaltReason Jit::Step() {
|
||||
return impl->Step();
|
||||
}
|
||||
|
||||
void Jit::ClearCache() {
|
||||
impl->ClearCache();
|
||||
}
|
||||
|
||||
void Jit::InvalidateCacheRange(u32 start_address, std::size_t length) {
|
||||
impl->InvalidateCacheRange(start_address, length);
|
||||
}
|
||||
|
||||
void Jit::Reset() {
|
||||
impl->Reset();
|
||||
}
|
||||
|
||||
void Jit::HaltExecution(HaltReason hr) {
|
||||
impl->HaltExecution(hr);
|
||||
}
|
||||
|
||||
void Jit::ClearHalt(HaltReason hr) {
|
||||
impl->ClearHalt(hr);
|
||||
}
|
||||
|
||||
std::array<u32, 16>& Jit::Regs() {
|
||||
return impl->Regs();
|
||||
}
|
||||
|
||||
const std::array<u32, 16>& Jit::Regs() const {
|
||||
return impl->Regs();
|
||||
}
|
||||
|
||||
std::array<u32, 64>& Jit::ExtRegs() {
|
||||
return impl->ExtRegs();
|
||||
}
|
||||
|
||||
const std::array<u32, 64>& Jit::ExtRegs() const {
|
||||
return impl->ExtRegs();
|
||||
}
|
||||
|
||||
u32 Jit::Cpsr() const {
|
||||
return impl->Cpsr();
|
||||
}
|
||||
|
||||
void Jit::SetCpsr(u32 value) {
|
||||
impl->SetCpsr(value);
|
||||
}
|
||||
|
||||
u32 Jit::Fpscr() const {
|
||||
return impl->Fpscr();
|
||||
}
|
||||
|
||||
void Jit::SetFpscr(u32 value) {
|
||||
impl->SetFpscr(value);
|
||||
}
|
||||
|
||||
void Jit::ClearExclusiveState() {
|
||||
impl->ClearExclusiveState();
|
||||
}
|
||||
|
||||
std::string Jit::Disassemble() const {
|
||||
return impl->Disassemble();
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::A32
|
||||
268
src/dynarmic/src/dynarmic/backend/loongarch64/a64_interface.cpp
Normal file
268
src/dynarmic/src/dynarmic/backend/loongarch64/a64_interface.cpp
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "dynarmic/interface/A64/a64.h"
|
||||
|
||||
namespace Dynarmic::A64 {
|
||||
|
||||
struct Jit::Impl final {
|
||||
explicit Impl(UserConfig conf_) : conf(std::move(conf_)) {}
|
||||
|
||||
HaltReason Run() {
|
||||
UNIMPLEMENTED();
|
||||
return halt_reason;
|
||||
}
|
||||
|
||||
HaltReason Step() {
|
||||
UNIMPLEMENTED();
|
||||
return halt_reason | HaltReason::Step;
|
||||
}
|
||||
|
||||
void ClearCache() {
|
||||
HaltExecution(HaltReason::CacheInvalidation);
|
||||
}
|
||||
|
||||
void InvalidateCacheRange(u64, std::size_t) {
|
||||
HaltExecution(HaltReason::CacheInvalidation);
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
regs = {};
|
||||
vectors = {};
|
||||
sp = 0;
|
||||
pc = 0;
|
||||
fpcr = 0;
|
||||
fpsr = 0;
|
||||
pstate = 0;
|
||||
halt_reason = {};
|
||||
}
|
||||
|
||||
void HaltExecution(HaltReason hr) {
|
||||
halt_reason |= hr;
|
||||
}
|
||||
|
||||
void ClearHalt(HaltReason hr) {
|
||||
halt_reason &= ~hr;
|
||||
}
|
||||
|
||||
u64 GetSP() const {
|
||||
return sp;
|
||||
}
|
||||
|
||||
void SetSP(u64 value) {
|
||||
sp = value;
|
||||
}
|
||||
|
||||
u64 GetPC() const {
|
||||
return pc;
|
||||
}
|
||||
|
||||
void SetPC(u64 value) {
|
||||
pc = value;
|
||||
}
|
||||
|
||||
u64 GetRegister(std::size_t index) const {
|
||||
return index == 31 ? sp : regs.at(index);
|
||||
}
|
||||
|
||||
void SetRegister(std::size_t index, u64 value) {
|
||||
if (index == 31) {
|
||||
sp = value;
|
||||
return;
|
||||
}
|
||||
regs.at(index) = value;
|
||||
}
|
||||
|
||||
std::array<u64, 31> GetRegisters() const {
|
||||
return regs;
|
||||
}
|
||||
|
||||
void SetRegisters(const std::array<u64, 31>& value) {
|
||||
regs = value;
|
||||
}
|
||||
|
||||
Vector GetVector(std::size_t index) const {
|
||||
return vectors.at(index);
|
||||
}
|
||||
|
||||
void SetVector(std::size_t index, Vector value) {
|
||||
vectors.at(index) = value;
|
||||
}
|
||||
|
||||
std::array<Vector, 32> GetVectors() const {
|
||||
return vectors;
|
||||
}
|
||||
|
||||
void SetVectors(const std::array<Vector, 32>& value) {
|
||||
vectors = value;
|
||||
}
|
||||
|
||||
u32 GetFpcr() const {
|
||||
return fpcr;
|
||||
}
|
||||
|
||||
void SetFpcr(u32 value) {
|
||||
fpcr = value;
|
||||
}
|
||||
|
||||
u32 GetFpsr() const {
|
||||
return fpsr;
|
||||
}
|
||||
|
||||
void SetFpsr(u32 value) {
|
||||
fpsr = value;
|
||||
}
|
||||
|
||||
u32 GetPstate() const {
|
||||
return pstate;
|
||||
}
|
||||
|
||||
void SetPstate(u32 value) {
|
||||
pstate = value;
|
||||
}
|
||||
|
||||
void ClearExclusiveState() {}
|
||||
|
||||
bool IsExecuting() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string Disassemble() const {
|
||||
return {};
|
||||
}
|
||||
|
||||
UserConfig conf;
|
||||
std::array<u64, 31> regs{};
|
||||
std::array<Vector, 32> vectors{};
|
||||
u64 sp = 0;
|
||||
u64 pc = 0;
|
||||
u32 fpcr = 0;
|
||||
u32 fpsr = 0;
|
||||
u32 pstate = 0;
|
||||
HaltReason halt_reason{};
|
||||
};
|
||||
|
||||
Jit::Jit(UserConfig conf) : impl(std::make_unique<Impl>(std::move(conf))) {}
|
||||
|
||||
Jit::~Jit() = default;
|
||||
|
||||
HaltReason Jit::Run() {
|
||||
return impl->Run();
|
||||
}
|
||||
|
||||
HaltReason Jit::Step() {
|
||||
return impl->Step();
|
||||
}
|
||||
|
||||
void Jit::ClearCache() {
|
||||
impl->ClearCache();
|
||||
}
|
||||
|
||||
void Jit::InvalidateCacheRange(u64 start_address, std::size_t length) {
|
||||
impl->InvalidateCacheRange(start_address, length);
|
||||
}
|
||||
|
||||
void Jit::Reset() {
|
||||
impl->Reset();
|
||||
}
|
||||
|
||||
void Jit::HaltExecution(HaltReason hr) {
|
||||
impl->HaltExecution(hr);
|
||||
}
|
||||
|
||||
void Jit::ClearHalt(HaltReason hr) {
|
||||
impl->ClearHalt(hr);
|
||||
}
|
||||
|
||||
u64 Jit::GetSP() const {
|
||||
return impl->GetSP();
|
||||
}
|
||||
|
||||
void Jit::SetSP(u64 value) {
|
||||
impl->SetSP(value);
|
||||
}
|
||||
|
||||
u64 Jit::GetPC() const {
|
||||
return impl->GetPC();
|
||||
}
|
||||
|
||||
void Jit::SetPC(u64 value) {
|
||||
impl->SetPC(value);
|
||||
}
|
||||
|
||||
u64 Jit::GetRegister(std::size_t index) const {
|
||||
return impl->GetRegister(index);
|
||||
}
|
||||
|
||||
void Jit::SetRegister(std::size_t index, u64 value) {
|
||||
impl->SetRegister(index, value);
|
||||
}
|
||||
|
||||
std::array<u64, 31> Jit::GetRegisters() const {
|
||||
return impl->GetRegisters();
|
||||
}
|
||||
|
||||
void Jit::SetRegisters(const std::array<u64, 31>& value) {
|
||||
impl->SetRegisters(value);
|
||||
}
|
||||
|
||||
Vector Jit::GetVector(std::size_t index) const {
|
||||
return impl->GetVector(index);
|
||||
}
|
||||
|
||||
void Jit::SetVector(std::size_t index, Vector value) {
|
||||
impl->SetVector(index, value);
|
||||
}
|
||||
|
||||
std::array<Vector, 32> Jit::GetVectors() const {
|
||||
return impl->GetVectors();
|
||||
}
|
||||
|
||||
void Jit::SetVectors(const std::array<Vector, 32>& value) {
|
||||
impl->SetVectors(value);
|
||||
}
|
||||
|
||||
u32 Jit::GetFpcr() const {
|
||||
return impl->GetFpcr();
|
||||
}
|
||||
|
||||
void Jit::SetFpcr(u32 value) {
|
||||
impl->SetFpcr(value);
|
||||
}
|
||||
|
||||
u32 Jit::GetFpsr() const {
|
||||
return impl->GetFpsr();
|
||||
}
|
||||
|
||||
void Jit::SetFpsr(u32 value) {
|
||||
impl->SetFpsr(value);
|
||||
}
|
||||
|
||||
u32 Jit::GetPstate() const {
|
||||
return impl->GetPstate();
|
||||
}
|
||||
|
||||
void Jit::SetPstate(u32 value) {
|
||||
impl->SetPstate(value);
|
||||
}
|
||||
|
||||
void Jit::ClearExclusiveState() {
|
||||
impl->ClearExclusiveState();
|
||||
}
|
||||
|
||||
bool Jit::IsExecuting() const {
|
||||
return impl->IsExecuting();
|
||||
}
|
||||
|
||||
std::string Jit::Disassemble() const {
|
||||
return impl->Disassemble();
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::A64
|
||||
23
src/dynarmic/src/dynarmic/backend/loongarch64/code_block.h
Normal file
23
src/dynarmic/src/dynarmic/backend/loongarch64/code_block.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Dynarmic::Backend::LoongArch64 {
|
||||
|
||||
class CodeBlock {
|
||||
public:
|
||||
template<typename T>
|
||||
T ptr() const noexcept {
|
||||
return reinterpret_cast<T>(mem);
|
||||
}
|
||||
|
||||
private:
|
||||
u8* mem = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Dynarmic::Backend::LoongArch64
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "dynarmic/interface/exclusive_monitor.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace Dynarmic {
|
||||
|
||||
ExclusiveMonitor::ExclusiveMonitor(std::size_t processor_count)
|
||||
: exclusive_addresses(processor_count, INVALID_EXCLUSIVE_ADDRESS), exclusive_values(processor_count) {}
|
||||
|
||||
size_t ExclusiveMonitor::GetProcessorCount() const {
|
||||
return exclusive_addresses.size();
|
||||
}
|
||||
|
||||
void ExclusiveMonitor::Lock() {
|
||||
lock.Lock();
|
||||
}
|
||||
|
||||
void ExclusiveMonitor::Unlock() {
|
||||
lock.Unlock();
|
||||
}
|
||||
|
||||
bool ExclusiveMonitor::CheckAndClear(std::size_t processor_id, VAddr address) {
|
||||
const VAddr masked_address = address & RESERVATION_GRANULE_MASK;
|
||||
|
||||
Lock();
|
||||
if (exclusive_addresses[processor_id] != masked_address) {
|
||||
Unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
for (VAddr& other_address : exclusive_addresses) {
|
||||
if (other_address == masked_address) {
|
||||
other_address = INVALID_EXCLUSIVE_ADDRESS;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ExclusiveMonitor::Clear() {
|
||||
Lock();
|
||||
std::fill(exclusive_addresses.begin(), exclusive_addresses.end(), INVALID_EXCLUSIVE_ADDRESS);
|
||||
Unlock();
|
||||
}
|
||||
|
||||
void ExclusiveMonitor::ClearProcessor(std::size_t processor_id) {
|
||||
Lock();
|
||||
exclusive_addresses[processor_id] = INVALID_EXCLUSIVE_ADDRESS;
|
||||
Unlock();
|
||||
}
|
||||
|
||||
} // namespace Dynarmic
|
||||
14
src/dynarmic/src/dynarmic/common/spin_lock_loongarch64.cpp
Normal file
14
src/dynarmic/src/dynarmic/common/spin_lock_loongarch64.cpp
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "dynarmic/common/spin_lock.h"
|
||||
|
||||
namespace Dynarmic {
|
||||
|
||||
void SpinLock::Lock() noexcept {
|
||||
}
|
||||
|
||||
void SpinLock::Unlock() noexcept {
|
||||
}
|
||||
|
||||
} // namespace Dynarmic
|
||||
|
|
@ -9,6 +9,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <tuple>
|
||||
|
||||
#include "common/assert.h"
|
||||
|
||||
|
|
@ -31,6 +32,10 @@ public:
|
|||
, expected{expected}
|
||||
{}
|
||||
|
||||
constexpr Matcher(std::tuple<T, T> t) noexcept
|
||||
: Matcher(std::get<0>(t), std::get<1>(t))
|
||||
{}
|
||||
|
||||
/// @brief Gets the mask for this instruction.
|
||||
constexpr inline T GetMask() const noexcept {
|
||||
return mask;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue