diff options
Diffstat (limited to 'src/common/arm64/native_clock.cpp')
| -rw-r--r-- | src/common/arm64/native_clock.cpp | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/src/common/arm64/native_clock.cpp b/src/common/arm64/native_clock.cpp new file mode 100644 index 000000000..88fdba527 --- /dev/null +++ b/src/common/arm64/native_clock.cpp | |||
| @@ -0,0 +1,72 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/arm64/native_clock.h" | ||
| 5 | |||
| 6 | namespace Common::Arm64 { | ||
| 7 | |||
| 8 | namespace { | ||
| 9 | |||
| 10 | NativeClock::FactorType GetFixedPointFactor(u64 num, u64 den) { | ||
| 11 | return (static_cast<NativeClock::FactorType>(num) << 64) / den; | ||
| 12 | } | ||
| 13 | |||
| 14 | u64 MultiplyHigh(u64 m, NativeClock::FactorType factor) { | ||
| 15 | return static_cast<u64>((m * factor) >> 64); | ||
| 16 | } | ||
| 17 | |||
| 18 | } // namespace | ||
| 19 | |||
| 20 | NativeClock::NativeClock() { | ||
| 21 | const u64 host_cntfrq = GetHostCNTFRQ(); | ||
| 22 | ns_cntfrq_factor = GetFixedPointFactor(NsRatio::den, host_cntfrq); | ||
| 23 | us_cntfrq_factor = GetFixedPointFactor(UsRatio::den, host_cntfrq); | ||
| 24 | ms_cntfrq_factor = GetFixedPointFactor(MsRatio::den, host_cntfrq); | ||
| 25 | guest_cntfrq_factor = GetFixedPointFactor(CNTFRQ, host_cntfrq); | ||
| 26 | gputick_cntfrq_factor = GetFixedPointFactor(GPUTickFreq, host_cntfrq); | ||
| 27 | } | ||
| 28 | |||
| 29 | std::chrono::nanoseconds NativeClock::GetTimeNS() const { | ||
| 30 | return std::chrono::nanoseconds{MultiplyHigh(GetHostTicksElapsed(), ns_cntfrq_factor)}; | ||
| 31 | } | ||
| 32 | |||
| 33 | std::chrono::microseconds NativeClock::GetTimeUS() const { | ||
| 34 | return std::chrono::microseconds{MultiplyHigh(GetHostTicksElapsed(), us_cntfrq_factor)}; | ||
| 35 | } | ||
| 36 | |||
| 37 | std::chrono::milliseconds NativeClock::GetTimeMS() const { | ||
| 38 | return std::chrono::milliseconds{MultiplyHigh(GetHostTicksElapsed(), ms_cntfrq_factor)}; | ||
| 39 | } | ||
| 40 | |||
| 41 | u64 NativeClock::GetCNTPCT() const { | ||
| 42 | return MultiplyHigh(GetHostTicksElapsed(), guest_cntfrq_factor); | ||
| 43 | } | ||
| 44 | |||
| 45 | u64 NativeClock::GetGPUTick() const { | ||
| 46 | return MultiplyHigh(GetHostTicksElapsed(), gputick_cntfrq_factor); | ||
| 47 | } | ||
| 48 | |||
| 49 | u64 NativeClock::GetHostTicksNow() const { | ||
| 50 | u64 cntvct_el0 = 0; | ||
| 51 | asm volatile("dsb ish\n\t" | ||
| 52 | "mrs %[cntvct_el0], cntvct_el0\n\t" | ||
| 53 | "dsb ish\n\t" | ||
| 54 | : [cntvct_el0] "=r"(cntvct_el0)); | ||
| 55 | return cntvct_el0; | ||
| 56 | } | ||
| 57 | |||
| 58 | u64 NativeClock::GetHostTicksElapsed() const { | ||
| 59 | return GetHostTicksNow(); | ||
| 60 | } | ||
| 61 | |||
| 62 | bool NativeClock::IsNative() const { | ||
| 63 | return true; | ||
| 64 | } | ||
| 65 | |||
| 66 | u64 NativeClock::GetHostCNTFRQ() { | ||
| 67 | u64 cntfrq_el0 = 0; | ||
| 68 | asm("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0)); | ||
| 69 | return cntfrq_el0; | ||
| 70 | } | ||
| 71 | |||
| 72 | } // namespace Common::Arm64 | ||