mirror of
				https://git.tardis.systems/mirrors/yuzu
				synced 2025-10-31 02:34:11 +01:00 
			
		
		
		
	common: add arm64 native clock
This commit is contained in:
		
							parent
							
								
									bd42bba71c
								
							
						
					
					
						commit
						21bc2c14bc
					
				| @ -189,6 +189,14 @@ if(ARCHITECTURE_x86_64) | ||||
|     target_link_libraries(common PRIVATE xbyak::xbyak) | ||||
| endif() | ||||
| 
 | ||||
| if (ARCHITECTURE_arm64 AND (ANDROID OR LINUX)) | ||||
|     target_sources(common | ||||
|         PRIVATE | ||||
|             arm64/native_clock.cpp | ||||
|             arm64/native_clock.h | ||||
|     ) | ||||
| endif() | ||||
| 
 | ||||
| if (MSVC) | ||||
|   target_compile_definitions(common PRIVATE | ||||
|     # The standard library doesn't provide any replacement for codecvt yet | ||||
|  | ||||
							
								
								
									
										72
									
								
								src/common/arm64/native_clock.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								src/common/arm64/native_clock.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,72 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #include "common/arm64/native_clock.h" | ||||
| 
 | ||||
| namespace Common::Arm64 { | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| NativeClock::FactorType GetFixedPointFactor(u64 num, u64 den) { | ||||
|     return (static_cast<NativeClock::FactorType>(num) << 64) / den; | ||||
| } | ||||
| 
 | ||||
| u64 MultiplyHigh(u64 m, NativeClock::FactorType factor) { | ||||
|     return static_cast<u64>((m * factor) >> 64); | ||||
| } | ||||
| 
 | ||||
| } // namespace
 | ||||
| 
 | ||||
| NativeClock::NativeClock() { | ||||
|     const u64 host_cntfrq = GetHostCNTFRQ(); | ||||
|     ns_cntfrq_factor = GetFixedPointFactor(NsRatio::den, host_cntfrq); | ||||
|     us_cntfrq_factor = GetFixedPointFactor(UsRatio::den, host_cntfrq); | ||||
|     ms_cntfrq_factor = GetFixedPointFactor(MsRatio::den, host_cntfrq); | ||||
|     guest_cntfrq_factor = GetFixedPointFactor(CNTFRQ, host_cntfrq); | ||||
|     gputick_cntfrq_factor = GetFixedPointFactor(GPUTickFreq, host_cntfrq); | ||||
| } | ||||
| 
 | ||||
| std::chrono::nanoseconds NativeClock::GetTimeNS() const { | ||||
|     return std::chrono::nanoseconds{MultiplyHigh(GetHostTicksElapsed(), ns_cntfrq_factor)}; | ||||
| } | ||||
| 
 | ||||
| std::chrono::microseconds NativeClock::GetTimeUS() const { | ||||
|     return std::chrono::microseconds{MultiplyHigh(GetHostTicksElapsed(), us_cntfrq_factor)}; | ||||
| } | ||||
| 
 | ||||
| std::chrono::milliseconds NativeClock::GetTimeMS() const { | ||||
|     return std::chrono::milliseconds{MultiplyHigh(GetHostTicksElapsed(), ms_cntfrq_factor)}; | ||||
| } | ||||
| 
 | ||||
| u64 NativeClock::GetCNTPCT() const { | ||||
|     return MultiplyHigh(GetHostTicksElapsed(), guest_cntfrq_factor); | ||||
| } | ||||
| 
 | ||||
| u64 NativeClock::GetGPUTick() const { | ||||
|     return MultiplyHigh(GetHostTicksElapsed(), gputick_cntfrq_factor); | ||||
| } | ||||
| 
 | ||||
| u64 NativeClock::GetHostTicksNow() const { | ||||
|     u64 cntvct_el0 = 0; | ||||
|     asm volatile("dsb ish\n\t" | ||||
|                  "mrs %[cntvct_el0], cntvct_el0\n\t" | ||||
|                  "dsb ish\n\t" | ||||
|                  : [cntvct_el0] "=r"(cntvct_el0)); | ||||
|     return cntvct_el0; | ||||
| } | ||||
| 
 | ||||
| u64 NativeClock::GetHostTicksElapsed() const { | ||||
|     return GetHostTicksNow(); | ||||
| } | ||||
| 
 | ||||
| bool NativeClock::IsNative() const { | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| u64 NativeClock::GetHostCNTFRQ() { | ||||
|     u64 cntfrq_el0 = 0; | ||||
|     asm("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0)); | ||||
|     return cntfrq_el0; | ||||
| } | ||||
| 
 | ||||
| } // namespace Common::Arm64
 | ||||
							
								
								
									
										47
									
								
								src/common/arm64/native_clock.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/common/arm64/native_clock.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "common/wall_clock.h" | ||||
| 
 | ||||
| namespace Common::Arm64 { | ||||
| 
 | ||||
| class NativeClock final : public WallClock { | ||||
| public: | ||||
|     explicit NativeClock(); | ||||
| 
 | ||||
|     std::chrono::nanoseconds GetTimeNS() const override; | ||||
| 
 | ||||
|     std::chrono::microseconds GetTimeUS() const override; | ||||
| 
 | ||||
|     std::chrono::milliseconds GetTimeMS() const override; | ||||
| 
 | ||||
|     u64 GetCNTPCT() const override; | ||||
| 
 | ||||
|     u64 GetGPUTick() const override; | ||||
| 
 | ||||
|     u64 GetHostTicksNow() const override; | ||||
| 
 | ||||
|     u64 GetHostTicksElapsed() const override; | ||||
| 
 | ||||
|     bool IsNative() const override; | ||||
| 
 | ||||
|     static u64 GetHostCNTFRQ(); | ||||
| 
 | ||||
| public: | ||||
|     using FactorType = unsigned __int128; | ||||
| 
 | ||||
|     FactorType GetGuestCNTFRQFactor() const { | ||||
|         return guest_cntfrq_factor; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     FactorType ns_cntfrq_factor; | ||||
|     FactorType us_cntfrq_factor; | ||||
|     FactorType ms_cntfrq_factor; | ||||
|     FactorType guest_cntfrq_factor; | ||||
|     FactorType gputick_cntfrq_factor; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Common::Arm64
 | ||||
| @ -10,6 +10,10 @@ | ||||
| #include "common/x64/rdtsc.h" | ||||
| #endif | ||||
| 
 | ||||
| #if defined(ARCHITECTURE_arm64) && defined(__linux__) | ||||
| #include "common/arm64/native_clock.h" | ||||
| #endif | ||||
| 
 | ||||
| namespace Common { | ||||
| 
 | ||||
| class StandardWallClock final : public WallClock { | ||||
| @ -53,7 +57,7 @@ private: | ||||
| }; | ||||
| 
 | ||||
| std::unique_ptr<WallClock> CreateOptimalClock() { | ||||
| #ifdef ARCHITECTURE_x86_64 | ||||
| #if defined(ARCHITECTURE_x86_64) | ||||
|     const auto& caps = GetCPUCaps(); | ||||
| 
 | ||||
|     if (caps.invariant_tsc && caps.tsc_frequency >= std::nano::den) { | ||||
| @ -64,6 +68,8 @@ std::unique_ptr<WallClock> CreateOptimalClock() { | ||||
|         // - Is not more precise than 1 GHz (1ns resolution)
 | ||||
|         return std::make_unique<StandardWallClock>(); | ||||
|     } | ||||
| #elif defined(ARCHITECTURE_arm64) && defined(__linux__) | ||||
|     return std::make_unique<Arm64::NativeClock>(); | ||||
| #else | ||||
|     return std::make_unique<StandardWallClock>(); | ||||
| #endif | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user