summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Liam2023-10-08 11:32:32 -0400
committerGravatar Liam2023-10-08 12:54:23 -0400
commit21bc2c14bc7408427a8b4851a7a3f15251f2afa8 (patch)
tree69597208c660a1af323b7e6dc5ff8e804e555682 /src
parentMerge pull request #11656 from liamwhite/recreate-surface-automatically (diff)
downloadyuzu-21bc2c14bc7408427a8b4851a7a3f15251f2afa8.tar.gz
yuzu-21bc2c14bc7408427a8b4851a7a3f15251f2afa8.tar.xz
yuzu-21bc2c14bc7408427a8b4851a7a3f15251f2afa8.zip
common: add arm64 native clock
Diffstat (limited to 'src')
-rw-r--r--src/common/CMakeLists.txt8
-rw-r--r--src/common/arm64/native_clock.cpp72
-rw-r--r--src/common/arm64/native_clock.h47
-rw-r--r--src/common/wall_clock.cpp8
4 files changed, 134 insertions, 1 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 416203c59..8a1861051 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -189,6 +189,14 @@ if(ARCHITECTURE_x86_64)
189 target_link_libraries(common PRIVATE xbyak::xbyak) 189 target_link_libraries(common PRIVATE xbyak::xbyak)
190endif() 190endif()
191 191
192if (ARCHITECTURE_arm64 AND (ANDROID OR LINUX))
193 target_sources(common
194 PRIVATE
195 arm64/native_clock.cpp
196 arm64/native_clock.h
197 )
198endif()
199
192if (MSVC) 200if (MSVC)
193 target_compile_definitions(common PRIVATE 201 target_compile_definitions(common PRIVATE
194 # The standard library doesn't provide any replacement for codecvt yet 202 # The standard library doesn't provide any replacement for codecvt yet
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
6namespace Common::Arm64 {
7
8namespace {
9
10NativeClock::FactorType GetFixedPointFactor(u64 num, u64 den) {
11 return (static_cast<NativeClock::FactorType>(num) << 64) / den;
12}
13
14u64 MultiplyHigh(u64 m, NativeClock::FactorType factor) {
15 return static_cast<u64>((m * factor) >> 64);
16}
17
18} // namespace
19
20NativeClock::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
29std::chrono::nanoseconds NativeClock::GetTimeNS() const {
30 return std::chrono::nanoseconds{MultiplyHigh(GetHostTicksElapsed(), ns_cntfrq_factor)};
31}
32
33std::chrono::microseconds NativeClock::GetTimeUS() const {
34 return std::chrono::microseconds{MultiplyHigh(GetHostTicksElapsed(), us_cntfrq_factor)};
35}
36
37std::chrono::milliseconds NativeClock::GetTimeMS() const {
38 return std::chrono::milliseconds{MultiplyHigh(GetHostTicksElapsed(), ms_cntfrq_factor)};
39}
40
41u64 NativeClock::GetCNTPCT() const {
42 return MultiplyHigh(GetHostTicksElapsed(), guest_cntfrq_factor);
43}
44
45u64 NativeClock::GetGPUTick() const {
46 return MultiplyHigh(GetHostTicksElapsed(), gputick_cntfrq_factor);
47}
48
49u64 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
58u64 NativeClock::GetHostTicksElapsed() const {
59 return GetHostTicksNow();
60}
61
62bool NativeClock::IsNative() const {
63 return true;
64}
65
66u64 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
diff --git a/src/common/arm64/native_clock.h b/src/common/arm64/native_clock.h
new file mode 100644
index 000000000..a28b419f2
--- /dev/null
+++ b/src/common/arm64/native_clock.h
@@ -0,0 +1,47 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "common/wall_clock.h"
7
8namespace Common::Arm64 {
9
10class NativeClock final : public WallClock {
11public:
12 explicit NativeClock();
13
14 std::chrono::nanoseconds GetTimeNS() const override;
15
16 std::chrono::microseconds GetTimeUS() const override;
17
18 std::chrono::milliseconds GetTimeMS() const override;
19
20 u64 GetCNTPCT() const override;
21
22 u64 GetGPUTick() const override;
23
24 u64 GetHostTicksNow() const override;
25
26 u64 GetHostTicksElapsed() const override;
27
28 bool IsNative() const override;
29
30 static u64 GetHostCNTFRQ();
31
32public:
33 using FactorType = unsigned __int128;
34
35 FactorType GetGuestCNTFRQFactor() const {
36 return guest_cntfrq_factor;
37 }
38
39private:
40 FactorType ns_cntfrq_factor;
41 FactorType us_cntfrq_factor;
42 FactorType ms_cntfrq_factor;
43 FactorType guest_cntfrq_factor;
44 FactorType gputick_cntfrq_factor;
45};
46
47} // namespace Common::Arm64
diff --git a/src/common/wall_clock.cpp b/src/common/wall_clock.cpp
index 71e15ab4c..caca9a123 100644
--- a/src/common/wall_clock.cpp
+++ b/src/common/wall_clock.cpp
@@ -10,6 +10,10 @@
10#include "common/x64/rdtsc.h" 10#include "common/x64/rdtsc.h"
11#endif 11#endif
12 12
13#if defined(ARCHITECTURE_arm64) && defined(__linux__)
14#include "common/arm64/native_clock.h"
15#endif
16
13namespace Common { 17namespace Common {
14 18
15class StandardWallClock final : public WallClock { 19class StandardWallClock final : public WallClock {
@@ -53,7 +57,7 @@ private:
53}; 57};
54 58
55std::unique_ptr<WallClock> CreateOptimalClock() { 59std::unique_ptr<WallClock> CreateOptimalClock() {
56#ifdef ARCHITECTURE_x86_64 60#if defined(ARCHITECTURE_x86_64)
57 const auto& caps = GetCPUCaps(); 61 const auto& caps = GetCPUCaps();
58 62
59 if (caps.invariant_tsc && caps.tsc_frequency >= std::nano::den) { 63 if (caps.invariant_tsc && caps.tsc_frequency >= std::nano::den) {
@@ -64,6 +68,8 @@ std::unique_ptr<WallClock> CreateOptimalClock() {
64 // - Is not more precise than 1 GHz (1ns resolution) 68 // - Is not more precise than 1 GHz (1ns resolution)
65 return std::make_unique<StandardWallClock>(); 69 return std::make_unique<StandardWallClock>();
66 } 70 }
71#elif defined(ARCHITECTURE_arm64) && defined(__linux__)
72 return std::make_unique<Arm64::NativeClock>();
67#else 73#else
68 return std::make_unique<StandardWallClock>(); 74 return std::make_unique<StandardWallClock>();
69#endif 75#endif