4 changed files with 134 additions and 1 deletions
-
8src/common/CMakeLists.txt
-
72src/common/arm64/native_clock.cpp
-
47src/common/arm64/native_clock.h
-
8src/common/wall_clock.cpp
@ -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
|
|||
@ -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 |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue