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