mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2025-01-14 16:40:04 +00:00
4b321c003c
On some devices, checking the system counter clock frequency will return 0. Substitute in the correct values to prevent issues.
92 lines
2.7 KiB
C++
92 lines
2.7 KiB
C++
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#ifdef ANDROID
|
|
#include <sys/system_properties.h>
|
|
#endif
|
|
#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;
|
|
std::string_view board{""};
|
|
#ifdef ANDROID
|
|
char buffer[PROP_VALUE_MAX];
|
|
int len{__system_property_get("ro.product.board", buffer)};
|
|
board = std::string_view(buffer, static_cast<size_t>(len));
|
|
#endif
|
|
if (board == "s5e9925") { // Exynos 2200
|
|
cntfrq_el0 = 25600000;
|
|
} else if (board == "exynos2100") { // Exynos 2100
|
|
cntfrq_el0 = 26000000;
|
|
} else if (board == "exynos9810") { // Exynos 9810
|
|
cntfrq_el0 = 26000000;
|
|
} else if (board == "s5e8825") { // Exynos 1280
|
|
cntfrq_el0 = 26000000;
|
|
} else {
|
|
asm("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0));
|
|
}
|
|
return cntfrq_el0;
|
|
}
|
|
|
|
} // namespace Common::Arm64
|