Browse Source
[dynarmic] bootstrap loongarch64 host build (#4015)
[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>pull/4025/head
committed by
crueter
No known key found for this signature in database
GPG Key ID: 425ACD2D4830EBC6
15 changed files with 607 additions and 9 deletions
-
5externals/CMakeLists.txt
-
6externals/cpmfile.json
-
2src/CMakeLists.txt
-
2src/core/CMakeLists.txt
-
4src/dynarmic/CMakeLists.txt
-
14src/dynarmic/src/dynarmic/CMakeLists.txt
-
10src/dynarmic/src/dynarmic/backend/exception_handler.h
-
6src/dynarmic/src/dynarmic/backend/exception_handler_generic.cpp
-
33src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp
-
170src/dynarmic/src/dynarmic/backend/loongarch64/a32_interface.cpp
-
268src/dynarmic/src/dynarmic/backend/loongarch64/a64_interface.cpp
-
23src/dynarmic/src/dynarmic/backend/loongarch64/code_block.h
-
54src/dynarmic/src/dynarmic/backend/loongarch64/exclusive_monitor.cpp
-
14src/dynarmic/src/dynarmic/common/spin_lock_loongarch64.cpp
-
5src/dynarmic/src/dynarmic/frontend/decoder/matcher.h
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue