[a64] Implement raw clock with CNTVCT_EL0
Implements a raw clock by directly accessing the `CNTVCT_EL0` and `CNTFRQ_EL0` registers by using `mrs` intrinsics. Should allow for a raw-clock to work on all ARM platforms without having to make a per-platform implementation for any further a64 platforms like MacOS or Linux or Android and such.
This commit is contained in:
@@ -26,8 +26,9 @@ DEFINE_bool(clock_no_scaling, false,
|
|||||||
"Guest system time is directly pulled from host.",
|
"Guest system time is directly pulled from host.",
|
||||||
"CPU");
|
"CPU");
|
||||||
DEFINE_bool(clock_source_raw, false,
|
DEFINE_bool(clock_source_raw, false,
|
||||||
"Use the RDTSC instruction as the time source. "
|
"On x64, Use the RDTSC instruction as the time source. Requires "
|
||||||
"Host CPU must support invariant TSC.",
|
"invariant TSC. "
|
||||||
|
"On a64, Use the CNTVCT_EL0 register as the time source",
|
||||||
"CPU");
|
"CPU");
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
#include "xenia/base/cvar.h"
|
#include "xenia/base/cvar.h"
|
||||||
#include "xenia/base/platform.h"
|
#include "xenia/base/platform.h"
|
||||||
|
|
||||||
#if XE_ARCH_AMD64
|
#if XE_ARCH_AMD64 || XE_ARCH_ARM64
|
||||||
#define XE_CLOCK_RAW_AVAILABLE 1
|
#define XE_CLOCK_RAW_AVAILABLE 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
37
src/xenia/base/clock_arm64.cc
Normal file
37
src/xenia/base/clock_arm64.cc
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2026 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xenia/base/clock.h"
|
||||||
|
#include "xenia/base/platform.h"
|
||||||
|
|
||||||
|
#if XE_ARCH_ARM64 && XE_CLOCK_RAW_AVAILABLE
|
||||||
|
|
||||||
|
// Wrap all these different cpu compiler intrinsics.
|
||||||
|
// So no inline assembler here and the compiler will remove the clutter.
|
||||||
|
#if XE_COMPILER_MSVC
|
||||||
|
#include <intrin.h>
|
||||||
|
constexpr uint32_t CNTFRQ_EL0 = ARM64_SYSREG(3, 3, 14, 0, 0);
|
||||||
|
constexpr uint32_t CNTVCT_EL0 = ARM64_SYSREG(3, 3, 14, 0, 2);
|
||||||
|
#define xe_cpu_mrs(reg) _ReadStatusReg(reg)
|
||||||
|
#elif XE_COMPILER_CLANG || XE_COMPILER_GNUC
|
||||||
|
#include <arm_acle.h>
|
||||||
|
#define xe_cpu_mrs(reg) __arm_rsr64(#reg)
|
||||||
|
#else
|
||||||
|
#error "No cpu instruction wrappers for current compiler implemented."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
XE_NOINLINE
|
||||||
|
uint64_t Clock::host_tick_frequency_raw() { return xe_cpu_mrs(CNTFRQ_EL0); }
|
||||||
|
XE_NOINLINE
|
||||||
|
uint64_t Clock::host_tick_count_raw() { return xe_cpu_mrs(CNTVCT_EL0); }
|
||||||
|
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user