From c13759454fa97248f2fd671d6a0de5144f317e7a Mon Sep 17 00:00:00 2001 From: xbzk Date: Wed, 10 Jun 2026 07:25:35 -0300 Subject: [PATCH] [patcher] CNTFRQ_EL0 impl based on CNTVCT_EL0 --- src/core/arm/nce/patcher.cpp | 19 ++++++++++++++++++- src/core/arm/nce/patcher.h | 2 ++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/core/arm/nce/patcher.cpp b/src/core/arm/nce/patcher.cpp index 79ff3b1e31..7d2041d4d2 100644 --- a/src/core/arm/nce/patcher.cpp +++ b/src/core/arm/nce/patcher.cpp @@ -145,7 +145,14 @@ bool Patcher::PatchText(std::span program_image, const Kernel::CodeSet // MRS Xn, CNTFRQ_EL0 if (auto mrs = MRS{inst}; mrs.Verify() && mrs.GetSystemReg() == CntfrqEl0) { - UNREACHABLE(); + bool pre_buffer = false; + auto ret = AddRelocations(pre_buffer); + if (pre_buffer) { + WriteCntfrqHandler(ret, oaknut::XReg{static_cast(mrs.GetRt())}, c_pre); + } else { + WriteCntfrqHandler(ret, oaknut::XReg{static_cast(mrs.GetRt())}, c); + } + continue; } // MSR TPIDR_EL0, Xn @@ -577,6 +584,16 @@ void Patcher::WriteMsrHandler(ModuleDestLabel module_dest, oaknut::XReg src_reg, this->BranchToModule(module_dest); } +void Patcher::WriteCntfrqHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg, oaknut::VectorCodeGenerator& cg) { + cg.MOV(dest_reg, Common::WallClock::CNTFRQ); + + // Jump back to the instruction after the emulated MRS. + if (&cg == &c_pre) + this->BranchToModulePre(module_dest); + else + this->BranchToModule(module_dest); +} + void Patcher::WriteCntpctHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg, oaknut::VectorCodeGenerator& cg) { #if defined(HAS_NCE) static Common::WallClock clock(false, 1); diff --git a/src/core/arm/nce/patcher.h b/src/core/arm/nce/patcher.h index 980a0c81e0..04d8534351 100644 --- a/src/core/arm/nce/patcher.h +++ b/src/core/arm/nce/patcher.h @@ -80,6 +80,7 @@ private: void WriteSvcTrampoline(ModuleDestLabel module_dest, u32 svc_id, oaknut::VectorCodeGenerator& code, oaknut::Label& save_ctx, oaknut::Label& load_ctx); void WriteMrsHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg, oaknut::SystemReg src_reg, oaknut::VectorCodeGenerator& code); void WriteMsrHandler(ModuleDestLabel module_dest, oaknut::XReg src_reg, oaknut::VectorCodeGenerator& code); + void WriteCntfrqHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg, oaknut::VectorCodeGenerator& code); void WriteCntpctHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg, oaknut::VectorCodeGenerator& code); // Convenience wrappers using default code generator @@ -90,6 +91,7 @@ private: void WriteSvcTrampoline(ModuleDestLabel module_dest, u32 svc_id) { WriteSvcTrampoline(module_dest, svc_id, c, m_save_context, m_load_context); } void WriteMrsHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg, oaknut::SystemReg src_reg) { WriteMrsHandler(module_dest, dest_reg, src_reg, c); } void WriteMsrHandler(ModuleDestLabel module_dest, oaknut::XReg src_reg) { WriteMsrHandler(module_dest, src_reg, c); } + void WriteCntfrqHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg) { WriteCntfrqHandler(module_dest, dest_reg, c); } void WriteCntpctHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg) { WriteCntpctHandler(module_dest, dest_reg, c); } private: