mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-05-16 16:57:00 +02:00
[common] remove ptr indirection on WallClock (#3864)
also devirtualizes manually since compiler doesn't do it with LTO Signed-off-by: lizzie <lizzie@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3864 Reviewed-by: crueter <crueter@eden-emu.dev>
This commit is contained in:
parent
a1f9e68f46
commit
975aa4e2f2
14 changed files with 300 additions and 404 deletions
|
|
@ -184,8 +184,6 @@ if(ARCHITECTURE_x86_64)
|
|||
x64/cpu_detect.h
|
||||
x64/cpu_wait.cpp
|
||||
x64/cpu_wait.h
|
||||
x64/native_clock.cpp
|
||||
x64/native_clock.h
|
||||
x64/rdtsc.cpp
|
||||
x64/rdtsc.h
|
||||
x64/xbyak_abi.h
|
||||
|
|
@ -193,10 +191,6 @@ if(ARCHITECTURE_x86_64)
|
|||
target_link_libraries(common PRIVATE xbyak::xbyak)
|
||||
endif()
|
||||
|
||||
if(HAS_NCE)
|
||||
target_sources(common PRIVATE arm64/native_clock.cpp arm64/native_clock.h)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
target_compile_definitions(
|
||||
common
|
||||
|
|
|
|||
|
|
@ -1,87 +0,0 @@
|
|||
// 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(GetUptime(), ns_cntfrq_factor)};
|
||||
}
|
||||
|
||||
std::chrono::microseconds NativeClock::GetTimeUS() const {
|
||||
return std::chrono::microseconds{MultiplyHigh(GetUptime(), us_cntfrq_factor)};
|
||||
}
|
||||
|
||||
std::chrono::milliseconds NativeClock::GetTimeMS() const {
|
||||
return std::chrono::milliseconds{MultiplyHigh(GetUptime(), ms_cntfrq_factor)};
|
||||
}
|
||||
|
||||
s64 NativeClock::GetCNTPCT() const {
|
||||
return MultiplyHigh(GetUptime(), guest_cntfrq_factor);
|
||||
}
|
||||
|
||||
s64 NativeClock::GetGPUTick() const {
|
||||
return MultiplyHigh(GetUptime(), gputick_cntfrq_factor);
|
||||
}
|
||||
|
||||
s64 NativeClock::GetUptime() const {
|
||||
s64 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;
|
||||
}
|
||||
|
||||
bool NativeClock::IsNative() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
s64 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
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
// 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;
|
||||
|
||||
s64 GetCNTPCT() const override;
|
||||
|
||||
s64 GetGPUTick() const override;
|
||||
|
||||
s64 GetUptime() const override;
|
||||
|
||||
bool IsNative() const override;
|
||||
|
||||
static s64 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
|
||||
|
|
@ -1,77 +1,196 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/steady_clock.h"
|
||||
#include "common/uint128.h"
|
||||
#include "common/wall_clock.h"
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <sys/system_properties.h>
|
||||
#endif
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
#include "common/x64/cpu_detect.h"
|
||||
#include "common/x64/native_clock.h"
|
||||
#include "common/x64/rdtsc.h"
|
||||
#endif
|
||||
#ifdef HAS_NCE
|
||||
#include "common/arm64/native_clock.h"
|
||||
#endif
|
||||
|
||||
namespace Common {
|
||||
|
||||
class StandardWallClock final : public WallClock {
|
||||
public:
|
||||
explicit StandardWallClock() {}
|
||||
|
||||
std::chrono::nanoseconds GetTimeNS() const override {
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch());
|
||||
}
|
||||
|
||||
std::chrono::microseconds GetTimeUS() const override {
|
||||
return std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch());
|
||||
}
|
||||
|
||||
std::chrono::milliseconds GetTimeMS() const override {
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch());
|
||||
}
|
||||
|
||||
s64 GetCNTPCT() const override {
|
||||
return GetUptime() * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den;
|
||||
}
|
||||
|
||||
s64 GetGPUTick() const override {
|
||||
return GetUptime() * NsToGPUTickRatio::num / NsToGPUTickRatio::den;
|
||||
}
|
||||
|
||||
s64 GetUptime() const override {
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
std::chrono::steady_clock::now().time_since_epoch())
|
||||
.count();
|
||||
}
|
||||
|
||||
bool IsNative() const override {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<WallClock> CreateOptimalClock() {
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
const auto& caps = GetCPUCaps();
|
||||
WallClock::WallClock(bool invariant_, u64 rdtsc_frequency_) noexcept
|
||||
: invariant{invariant_}
|
||||
, rdtsc_frequency{rdtsc_frequency_}
|
||||
, ns_rdtsc_factor{GetFixedPoint64Factor(NsRatio::den, rdtsc_frequency_)}
|
||||
, us_rdtsc_factor{GetFixedPoint64Factor(UsRatio::den, rdtsc_frequency_)}
|
||||
, ms_rdtsc_factor{GetFixedPoint64Factor(MsRatio::den, rdtsc_frequency_)}
|
||||
, cntpct_rdtsc_factor{GetFixedPoint64Factor(CNTFRQ, rdtsc_frequency_)}
|
||||
, gputick_rdtsc_factor{GetFixedPoint64Factor(GPUTickFreq, rdtsc_frequency_)}
|
||||
{}
|
||||
|
||||
if (caps.invariant_tsc && caps.tsc_frequency >= std::nano::den) {
|
||||
return std::make_unique<X64::NativeClock>(caps.tsc_frequency);
|
||||
} else {
|
||||
// Fallback to StandardWallClock if the hardware TSC
|
||||
// - Is not invariant
|
||||
// - Is not more precise than 1 GHz (1ns resolution)
|
||||
return std::make_unique<StandardWallClock>();
|
||||
}
|
||||
std::chrono::nanoseconds WallClock::GetTimeNS() const {
|
||||
if (invariant)
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch());
|
||||
return std::chrono::nanoseconds{MultiplyHigh(GetUptime(), ns_rdtsc_factor)};
|
||||
}
|
||||
|
||||
std::chrono::microseconds WallClock::GetTimeUS() const {
|
||||
if (invariant)
|
||||
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch());
|
||||
return std::chrono::microseconds{MultiplyHigh(GetUptime(), us_rdtsc_factor)};
|
||||
}
|
||||
|
||||
std::chrono::milliseconds WallClock::GetTimeMS() const {
|
||||
if (invariant)
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
|
||||
return std::chrono::milliseconds{MultiplyHigh(GetUptime(), ms_rdtsc_factor)};
|
||||
}
|
||||
|
||||
s64 WallClock::GetCNTPCT() const {
|
||||
if (invariant)
|
||||
return GetUptime() * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den;
|
||||
return MultiplyHigh(GetUptime(), cntpct_rdtsc_factor);
|
||||
}
|
||||
|
||||
s64 WallClock::GetGPUTick() const {
|
||||
if (invariant)
|
||||
return GetUptime() * NsToGPUTickRatio::num / NsToGPUTickRatio::den;
|
||||
return MultiplyHigh(GetUptime(), gputick_rdtsc_factor);
|
||||
}
|
||||
|
||||
s64 WallClock::GetUptime() const {
|
||||
if (invariant)
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
|
||||
return s64(Common::X64::FencedRDTSC());
|
||||
}
|
||||
|
||||
bool WallClock::IsNative() const {
|
||||
if (invariant)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
#elif defined(HAS_NCE)
|
||||
return std::make_unique<Arm64::NativeClock>();
|
||||
namespace {
|
||||
|
||||
[[nodiscard]] WallClock::FactorType GetFixedPointFactor(u64 num, u64 den) noexcept {
|
||||
return (WallClock::FactorType(num) << 64) / den;
|
||||
}
|
||||
|
||||
[[nodiscard]] u64 MultiplyHigh(u64 m, WallClock::FactorType factor) noexcept {
|
||||
return static_cast<u64>((m * factor) >> 64);
|
||||
}
|
||||
|
||||
[[nodiscard]] s64 GetHostCNTFRQ() noexcept {
|
||||
u64 cntfrq_el0 = 0;
|
||||
#ifdef ANDROID
|
||||
std::string_view board{""};
|
||||
char buffer[PROP_VALUE_MAX];
|
||||
int len{__system_property_get("ro.product.board", buffer)};
|
||||
board = std::string_view(buffer, static_cast<size_t>(len));
|
||||
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 volatile("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0));
|
||||
}
|
||||
return cntfrq_el0;
|
||||
#else
|
||||
return std::make_unique<StandardWallClock>();
|
||||
asm volatile("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0));
|
||||
return cntfrq_el0;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
WallClock::WallClock(bool invariant_, u64 rdtsc_frequency_) noexcept {
|
||||
const u64 host_cntfrq = std::max<u64>(GetHostCNTFRQ(), 1);
|
||||
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 WallClock::GetTimeNS() const {
|
||||
return std::chrono::nanoseconds{MultiplyHigh(GetUptime(), ns_cntfrq_factor)};
|
||||
}
|
||||
|
||||
std::chrono::microseconds WallClock::GetTimeUS() const {
|
||||
return std::chrono::microseconds{MultiplyHigh(GetUptime(), us_cntfrq_factor)};
|
||||
}
|
||||
|
||||
std::chrono::milliseconds WallClock::GetTimeMS() const {
|
||||
return std::chrono::milliseconds{MultiplyHigh(GetUptime(), ms_cntfrq_factor)};
|
||||
}
|
||||
|
||||
s64 WallClock::GetCNTPCT() const {
|
||||
return MultiplyHigh(GetUptime(), guest_cntfrq_factor);
|
||||
}
|
||||
|
||||
s64 WallClock::GetGPUTick() const {
|
||||
return MultiplyHigh(GetUptime(), gputick_cntfrq_factor);
|
||||
}
|
||||
|
||||
s64 WallClock::GetUptime() const {
|
||||
s64 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;
|
||||
}
|
||||
|
||||
bool WallClock::IsNative() const {
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
WallClock::WallClock(bool invariant_, u64 rdtsc_frequency_) noexcept {}
|
||||
|
||||
std::chrono::nanoseconds WallClock::GetTimeNS() const {
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch());
|
||||
}
|
||||
|
||||
std::chrono::microseconds WallClock::GetTimeUS() const {
|
||||
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch());
|
||||
}
|
||||
|
||||
std::chrono::milliseconds WallClock::GetTimeMS() const {
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
|
||||
}
|
||||
|
||||
s64 WallClock::GetCNTPCT() const {
|
||||
return GetUptime() * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den;
|
||||
}
|
||||
|
||||
s64 WallClock::GetGPUTick() const {
|
||||
return GetUptime() * NsToGPUTickRatio::num / NsToGPUTickRatio::den;
|
||||
}
|
||||
|
||||
s64 WallClock::GetUptime() const {
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
|
||||
}
|
||||
|
||||
bool WallClock::IsNative() const {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
WallClock CreateOptimalClock() noexcept {
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
auto const& caps = GetCPUCaps();
|
||||
return WallClock(!(caps.invariant_tsc && caps.tsc_frequency >= std::nano::den), std::max<u64>(caps.tsc_frequency, 1));
|
||||
#elif defined(HAS_NCE)
|
||||
return WallClock(false, 1);
|
||||
#else
|
||||
return WallClock(true, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
|
|
@ -20,28 +20,28 @@ public:
|
|||
static constexpr u64 GPUTickFreq = 614'400'000; // GM20B GPU Tick Frequency = 614.4 MHz
|
||||
static constexpr u64 CPUTickFreq = 1'020'000'000; // T210/4 A57 CPU Tick Frequency = 1020.0 MHz
|
||||
|
||||
virtual ~WallClock() = default;
|
||||
explicit WallClock(bool invariant, u64 rdtsc_frequency_) noexcept;
|
||||
|
||||
/// @returns The time in nanoseconds since the construction of this clock.
|
||||
virtual std::chrono::nanoseconds GetTimeNS() const = 0;
|
||||
std::chrono::nanoseconds GetTimeNS() const;
|
||||
|
||||
/// @returns The time in microseconds since the construction of this clock.
|
||||
virtual std::chrono::microseconds GetTimeUS() const = 0;
|
||||
std::chrono::microseconds GetTimeUS() const;
|
||||
|
||||
/// @returns The time in milliseconds since the construction of this clock.
|
||||
virtual std::chrono::milliseconds GetTimeMS() const = 0;
|
||||
std::chrono::milliseconds GetTimeMS() const;
|
||||
|
||||
/// @returns The guest CNTPCT ticks since the construction of this clock.
|
||||
virtual s64 GetCNTPCT() const = 0;
|
||||
s64 GetCNTPCT() const;
|
||||
|
||||
/// @returns The guest GPU ticks since the construction of this clock.
|
||||
virtual s64 GetGPUTick() const = 0;
|
||||
s64 GetGPUTick() const;
|
||||
|
||||
/// @returns The raw host timer ticks since an indeterminate epoch.
|
||||
virtual s64 GetUptime() const = 0;
|
||||
s64 GetUptime() const;
|
||||
|
||||
/// @returns Whether the clock directly uses the host's hardware clock.
|
||||
virtual bool IsNative() const = 0;
|
||||
bool IsNative() const;
|
||||
|
||||
static inline u64 NSToCNTPCT(u64 ns) {
|
||||
return ns * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den;
|
||||
|
|
@ -85,8 +85,33 @@ protected:
|
|||
using CPUTickToUsRatio = std::ratio<std::micro::den, CPUTickFreq>;
|
||||
using CPUTickToCNTPCTRatio = std::ratio<CNTFRQ, CPUTickFreq>;
|
||||
using CPUTickToGPUTickRatio = std::ratio<GPUTickFreq, CPUTickFreq>;
|
||||
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
bool invariant;
|
||||
u64 rdtsc_frequency;
|
||||
u64 ns_rdtsc_factor;
|
||||
u64 us_rdtsc_factor;
|
||||
u64 ms_rdtsc_factor;
|
||||
u64 cntpct_rdtsc_factor;
|
||||
u64 gputick_rdtsc_factor;
|
||||
#elif defined(HAS_NCE)
|
||||
public:
|
||||
using FactorType = unsigned __int128;
|
||||
|
||||
FactorType GetGuestCNTFRQFactor() const {
|
||||
return guest_cntfrq_factor;
|
||||
}
|
||||
protected:
|
||||
FactorType ns_cntfrq_factor;
|
||||
FactorType us_cntfrq_factor;
|
||||
FactorType ms_cntfrq_factor;
|
||||
FactorType guest_cntfrq_factor;
|
||||
FactorType gputick_cntfrq_factor;
|
||||
#else
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
[[nodiscard]] std::unique_ptr<WallClock> CreateOptimalClock();
|
||||
[[nodiscard]] WallClock CreateOptimalClock() noexcept;
|
||||
|
||||
} // namespace Common
|
||||
|
|
|
|||
|
|
@ -1,46 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/uint128.h"
|
||||
#include "common/x64/native_clock.h"
|
||||
#include "common/x64/rdtsc.h"
|
||||
|
||||
namespace Common::X64 {
|
||||
|
||||
NativeClock::NativeClock(u64 rdtsc_frequency_)
|
||||
: rdtsc_frequency{rdtsc_frequency_}, ns_rdtsc_factor{GetFixedPoint64Factor(NsRatio::den,
|
||||
rdtsc_frequency)},
|
||||
us_rdtsc_factor{GetFixedPoint64Factor(UsRatio::den, rdtsc_frequency)},
|
||||
ms_rdtsc_factor{GetFixedPoint64Factor(MsRatio::den, rdtsc_frequency)},
|
||||
cntpct_rdtsc_factor{GetFixedPoint64Factor(CNTFRQ, rdtsc_frequency)},
|
||||
gputick_rdtsc_factor{GetFixedPoint64Factor(GPUTickFreq, rdtsc_frequency)} {}
|
||||
|
||||
std::chrono::nanoseconds NativeClock::GetTimeNS() const {
|
||||
return std::chrono::nanoseconds{MultiplyHigh(GetUptime(), ns_rdtsc_factor)};
|
||||
}
|
||||
|
||||
std::chrono::microseconds NativeClock::GetTimeUS() const {
|
||||
return std::chrono::microseconds{MultiplyHigh(GetUptime(), us_rdtsc_factor)};
|
||||
}
|
||||
|
||||
std::chrono::milliseconds NativeClock::GetTimeMS() const {
|
||||
return std::chrono::milliseconds{MultiplyHigh(GetUptime(), ms_rdtsc_factor)};
|
||||
}
|
||||
|
||||
s64 NativeClock::GetCNTPCT() const {
|
||||
return MultiplyHigh(GetUptime(), cntpct_rdtsc_factor);
|
||||
}
|
||||
|
||||
s64 NativeClock::GetGPUTick() const {
|
||||
return MultiplyHigh(GetUptime(), gputick_rdtsc_factor);
|
||||
}
|
||||
|
||||
s64 NativeClock::GetUptime() const {
|
||||
return static_cast<s64>(FencedRDTSC());
|
||||
}
|
||||
|
||||
bool NativeClock::IsNative() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Common::X64
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/wall_clock.h"
|
||||
|
||||
namespace Common::X64 {
|
||||
|
||||
class NativeClock final : public WallClock {
|
||||
public:
|
||||
explicit NativeClock(u64 rdtsc_frequency_);
|
||||
|
||||
std::chrono::nanoseconds GetTimeNS() const override;
|
||||
|
||||
std::chrono::microseconds GetTimeUS() const override;
|
||||
|
||||
std::chrono::milliseconds GetTimeMS() const override;
|
||||
|
||||
s64 GetCNTPCT() const override;
|
||||
|
||||
s64 GetGPUTick() const override;
|
||||
|
||||
s64 GetUptime() const override;
|
||||
|
||||
bool IsNative() const override;
|
||||
|
||||
private:
|
||||
u64 rdtsc_frequency;
|
||||
|
||||
u64 ns_rdtsc_factor;
|
||||
u64 us_rdtsc_factor;
|
||||
u64 ms_rdtsc_factor;
|
||||
u64 cntpct_rdtsc_factor;
|
||||
u64 gputick_rdtsc_factor;
|
||||
};
|
||||
|
||||
} // namespace Common::X64
|
||||
Loading…
Add table
Add a link
Reference in a new issue