diff --git a/src/dynarmic/CMakeLists.txt b/src/dynarmic/CMakeLists.txt index b033e7c1..a81fb0bc 100644 --- a/src/dynarmic/CMakeLists.txt +++ b/src/dynarmic/CMakeLists.txt @@ -390,6 +390,8 @@ elseif(ARCHITECTURE STREQUAL "arm64") backend/arm64/emit_arm64_vector_floating_point.cpp backend/arm64/emit_arm64_vector_saturation.cpp backend/arm64/emit_context.h + backend/arm64/fpsr_manager.cpp + backend/arm64/fpsr_manager.h backend/arm64/reg_alloc.cpp backend/arm64/reg_alloc.h backend/arm64/stack_layout.h diff --git a/src/dynarmic/backend/arm64/fpsr_manager.cpp b/src/dynarmic/backend/arm64/fpsr_manager.cpp new file mode 100644 index 00000000..8c697f5c --- /dev/null +++ b/src/dynarmic/backend/arm64/fpsr_manager.cpp @@ -0,0 +1,40 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2022 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#include "dynarmic/backend/arm64/fpsr_manager.h" + +#include + +#include "dynarmic/backend/arm64/abi.h" + +namespace Dynarmic::Backend::Arm64 { + +using namespace oaknut::util; + +FpsrManager::FpsrManager(oaknut::CodeGenerator& code, size_t state_fpsr_offset) + : code{code}, state_fpsr_offset{state_fpsr_offset} {} + +void FpsrManager::Spill() { + if (!fpsr_loaded) + return; + + code.LDR(Wscratch0, Xstate, state_fpsr_offset); + code.MSR(oaknut::SystemReg::FPSR, Xscratch1); + code.ORR(Wscratch0, Wscratch0, Wscratch1); + code.STR(Wscratch0, Xstate, state_fpsr_offset); + + fpsr_loaded = false; +} + +void FpsrManager::Load() { + if (fpsr_loaded) + return; + + code.MRS(XZR, oaknut::SystemReg::FPSR); + + fpsr_loaded = true; +} + +} // namespace Dynarmic::Backend::Arm64 diff --git a/src/dynarmic/backend/arm64/fpsr_manager.h b/src/dynarmic/backend/arm64/fpsr_manager.h new file mode 100644 index 00000000..7aa22eab --- /dev/null +++ b/src/dynarmic/backend/arm64/fpsr_manager.h @@ -0,0 +1,33 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2022 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#pragma once + +#include + +namespace oaknut { +struct PointerCodeGeneratorPolicy; +template +class BasicCodeGenerator; +using CodeGenerator = BasicCodeGenerator; +} // namespace oaknut + +namespace Dynarmic::Backend::Arm64 { + +class FpsrManager { +public: + explicit FpsrManager(oaknut::CodeGenerator& code, size_t state_fpsr_offset); + + void Spill(); + void Load(); + void Overwrite() { fpsr_loaded = false; } + +private: + oaknut::CodeGenerator& code; + size_t state_fpsr_offset; + bool fpsr_loaded = false; +}; + +} // namespace Dynarmic::Backend::Arm64