aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFeng Chen <vonchenplus@gmail.com>2026-09-17 19:50:19 +0200
committercrueter <crueter@eden-emu.dev>2026-09-17 19:50:19 +0200
commit0ce29be60874b24890ab9239cecf1bd67b924428 (patch)
treed0cf498acff9c64e3f6521290184fc0efc85e287 /src
parent1203082a8f1211ad6ce4d95f0c6947f7ecd27a55 (diff)
[common] Fix RDTSC nanosecond conversion (#4422)
Split the RDTSC ticks-per-nanosecond ratio into integer and Q0.64 fractional components. This avoids overflowing GetFixedPoint64Factor for TSC frequencies above 1 GHz while preserving the multiply-only conversion path. Use the invariant clock only above 1 GHz because the reverse nanoseconds-per-tick factor cannot represent an exact ratio of one. - [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions). - [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md) - [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability. ------------------- Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4422 Reviewed-by: lizzie <lizzie@eden-emu.dev> Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Diffstat (limited to 'src')
-rw-r--r--src/common/cpu_features.cpp7
-rw-r--r--src/common/cpu_features.h1
2 files changed, 5 insertions, 3 deletions
diff --git a/src/common/cpu_features.cpp b/src/common/cpu_features.cpp
index 2e02c47826..8ccb6847f7 100644
--- a/src/common/cpu_features.cpp
+++ b/src/common/cpu_features.cpp
@@ -244,7 +244,8 @@ WallClock::WallClock(bool invariant_, u64 rdtsc_frequency_) noexcept
, ns_rdtsc_factor{invariant_ ? GetFixedPoint64Factor(NsRatio::den, rdtsc_frequency_) : 0}
, us_rdtsc_factor{invariant_ ? GetFixedPoint64Factor(UsRatio::den, rdtsc_frequency_) : 0}
, ms_rdtsc_factor{invariant_ ? GetFixedPoint64Factor(MsRatio::den, rdtsc_frequency_) : 0}
- , rdtsc_ns_factor{invariant_ ? GetFixedPoint64Factor(rdtsc_frequency_, NsRatio::den) : 1}
+ , rdtsc_ns_integer{invariant_ ? rdtsc_frequency_ / NsRatio::den : 1}
+ , rdtsc_ns_factor{invariant_ ? GetFixedPoint64Factor(rdtsc_frequency_ % NsRatio::den, NsRatio::den) : 0}
, cntpct_rdtsc_factor{invariant_ ? GetFixedPoint64Factor(CNTFRQ, rdtsc_frequency_) : 0}
, gputick_rdtsc_factor{invariant_ ? GetFixedPoint64Factor(GPUTickFreq, rdtsc_frequency_) : 0}
, invariant{invariant_}
@@ -291,7 +292,7 @@ bool WallClock::IsNative() const {
}
u64 WallClock::NsToTicks(std::chrono::nanoseconds ns) const {
- return invariant ? MultiplyHigh(ns.count(), rdtsc_ns_factor) : ns.count();
+ return ns.count() * rdtsc_ns_integer + MultiplyHigh(ns.count(), rdtsc_ns_factor);
}
#elif defined(HAS_NCE)
namespace {
@@ -416,7 +417,7 @@ u64 WallClock::NsToTicks(std::chrono::nanoseconds ns) const {
const WallClock g_wall_clock = [] {
#if defined(ARCHITECTURE_x86_64)
auto const& caps = Common::g_cpu_caps;
- return WallClock(caps.invariant_tsc && caps.tsc_frequency >= std::nano::den, caps.tsc_frequency);
+ return WallClock(caps.invariant_tsc && caps.tsc_frequency > std::nano::den, caps.tsc_frequency);
#elif defined(HAS_NCE)
return WallClock(false, 1);
#else
diff --git a/src/common/cpu_features.h b/src/common/cpu_features.h
index 7dcb550f8f..61aa2767ab 100644
--- a/src/common/cpu_features.h
+++ b/src/common/cpu_features.h
@@ -96,6 +96,7 @@ public:
u64 ns_rdtsc_factor;
u64 us_rdtsc_factor;
u64 ms_rdtsc_factor;
+ u64 rdtsc_ns_integer;
u64 rdtsc_ns_factor;
u64 cntpct_rdtsc_factor;
u64 gputick_rdtsc_factor;