summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFernando Sahmkow <fsahmkow27@gmail.com>2020-02-10 16:20:40 +0100
committerFernando Sahmkow <fsahmkow27@gmail.com>2020-06-18 22:29:18 +0200
commite3524d114246a9221c766bdf1992777b208cbd67 (patch)
tree1454fe38bdafd94ada74ae5f1209a7466bbf4e78
parentCommon: Implement WallClock Interface and implement a native clock for x64 (diff)
downloadyuzu-e3524d114246a9221c766bdf1992777b208cbd67.tar
yuzu-e3524d114246a9221c766bdf1992777b208cbd67.tar.gz
yuzu-e3524d114246a9221c766bdf1992777b208cbd67.tar.bz2
yuzu-e3524d114246a9221c766bdf1992777b208cbd67.tar.lz
yuzu-e3524d114246a9221c766bdf1992777b208cbd67.tar.xz
yuzu-e3524d114246a9221c766bdf1992777b208cbd67.tar.zst
yuzu-e3524d114246a9221c766bdf1992777b208cbd67.zip
-rw-r--r--src/common/uint128.cpp22
-rw-r--r--src/common/uint128.h3
-rw-r--r--src/common/wall_clock.cpp13
-rw-r--r--src/common/wall_clock.h13
-rw-r--r--src/common/x64/native_clock.cpp47
-rw-r--r--src/core/host_timing.cpp3
6 files changed, 50 insertions, 51 deletions
diff --git a/src/common/uint128.cpp b/src/common/uint128.cpp
index 32bf56730..7e77588db 100644
--- a/src/common/uint128.cpp
+++ b/src/common/uint128.cpp
@@ -6,12 +6,34 @@
#include <intrin.h>
#pragma intrinsic(_umul128)
+#pragma intrinsic(_udiv128)
#endif
#include <cstring>
#include "common/uint128.h"
namespace Common {
+#ifdef _MSC_VER
+
+u64 MultiplyAndDivide64(u64 a, u64 b, u64 d) {
+ u128 r{};
+ r[0] = _umul128(a, b, &r[1]);
+ u64 remainder;
+ return _udiv128(r[1], r[0], d, &remainder);
+}
+
+#else
+
+u64 MultiplyAndDivide64(u64 a, u64 b, u64 d) {
+ const u64 diva = a / d;
+ const u64 moda = a % d;
+ const u64 divb = b / d;
+ const u64 modb = b % d;
+ return diva * b + moda * divb + moda * modb / d;
+}
+
+#endif
+
u128 Multiply64Into128(u64 a, u64 b) {
u128 result;
#ifdef _MSC_VER
diff --git a/src/common/uint128.h b/src/common/uint128.h
index a3be2a2cb..503cd2d0c 100644
--- a/src/common/uint128.h
+++ b/src/common/uint128.h
@@ -9,6 +9,9 @@
namespace Common {
+// This function multiplies 2 u64 values and divides it by a u64 value.
+u64 MultiplyAndDivide64(u64 a, u64 b, u64 d);
+
// This function multiplies 2 u64 values and produces a u128 value;
u128 Multiply64Into128(u64 a, u64 b);
diff --git a/src/common/wall_clock.cpp b/src/common/wall_clock.cpp
index eabbba9da..8f5e17fa4 100644
--- a/src/common/wall_clock.cpp
+++ b/src/common/wall_clock.cpp
@@ -58,7 +58,7 @@ private:
#ifdef ARCHITECTURE_x86_64
-WallClock* CreateBestMatchingClock(u32 emulated_cpu_frequency, u32 emulated_clock_frequency) {
+std::unique_ptr<WallClock> CreateBestMatchingClock(u32 emulated_cpu_frequency, u32 emulated_clock_frequency) {
const auto& caps = GetCPUCaps();
u64 rtsc_frequency = 0;
if (caps.invariant_tsc) {
@@ -70,19 +70,16 @@ WallClock* CreateBestMatchingClock(u32 emulated_cpu_frequency, u32 emulated_cloc
}
}
if (rtsc_frequency == 0) {
- return static_cast<WallClock*>(
- new StandardWallClock(emulated_cpu_frequency, emulated_clock_frequency));
+ return std::make_unique<StandardWallClock>(emulated_cpu_frequency, emulated_clock_frequency);
} else {
- return static_cast<WallClock*>(
- new X64::NativeClock(emulated_cpu_frequency, emulated_clock_frequency, rtsc_frequency));
+ return std::make_unique<X64::NativeClock>(emulated_cpu_frequency, emulated_clock_frequency, rtsc_frequency);
}
}
#else
-WallClock* CreateBestMatchingClock(u32 emulated_cpu_frequency, u32 emulated_clock_frequency) {
- return static_cast<WallClock*>(
- new StandardWallClock(emulated_cpu_frequency, emulated_clock_frequency));
+std::unique_ptr<WallClock> CreateBestMatchingClock(u32 emulated_cpu_frequency, u32 emulated_clock_frequency) {
+ return std::make_unique<StandardWallClock>(emulated_cpu_frequency, emulated_clock_frequency);
}
#endif
diff --git a/src/common/wall_clock.h b/src/common/wall_clock.h
index 6f763d74b..fc34429bb 100644
--- a/src/common/wall_clock.h
+++ b/src/common/wall_clock.h
@@ -5,6 +5,7 @@
#pragma once
#include <chrono>
+#include <memory>
#include "common/common_types.h"
@@ -12,10 +13,20 @@ namespace Common {
class WallClock {
public:
+
+ /// Returns current wall time in nanoseconds
virtual std::chrono::nanoseconds GetTimeNS() = 0;
+
+ /// Returns current wall time in microseconds
virtual std::chrono::microseconds GetTimeUS() = 0;
+
+ /// Returns current wall time in milliseconds
virtual std::chrono::milliseconds GetTimeMS() = 0;
+
+ /// Returns current wall time in emulated clock cycles
virtual u64 GetClockCycles() = 0;
+
+ /// Returns current wall time in emulated cpu cycles
virtual u64 GetCPUCycles() = 0;
/// Tells if the wall clock, uses the host CPU's hardware clock
@@ -35,6 +46,6 @@ private:
bool is_native;
};
-WallClock* CreateBestMatchingClock(u32 emulated_cpu_frequency, u32 emulated_clock_frequency);
+std::unique_ptr<WallClock> CreateBestMatchingClock(u32 emulated_cpu_frequency, u32 emulated_clock_frequency);
} // namespace Common
diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp
index c799111fd..26d4d0ba6 100644
--- a/src/common/x64/native_clock.cpp
+++ b/src/common/x64/native_clock.cpp
@@ -11,44 +11,11 @@
#include <x86intrin.h>
#endif
+#include "common/uint128.h"
#include "common/x64/native_clock.h"
namespace Common {
-#ifdef _MSC_VER
-
-namespace {
-
-struct uint128 {
- u64 low;
- u64 high;
-};
-
-u64 umuldiv64(u64 a, u64 b, u64 d) {
- uint128 r{};
- r.low = _umul128(a, b, &r.high);
- u64 remainder;
- return _udiv128(r.high, r.low, d, &remainder);
-}
-
-} // namespace
-
-#else
-
-namespace {
-
-u64 umuldiv64(u64 a, u64 b, u64 d) {
- const u64 diva = a / d;
- const u64 moda = a % d;
- const u64 divb = b / d;
- const u64 modb = b % d;
- return diva * b + moda * divb + moda * modb / d;
-}
-
-} // namespace
-
-#endif
-
u64 EstimateRDTSCFrequency() {
const auto milli_10 = std::chrono::milliseconds{10};
// get current time
@@ -70,7 +37,7 @@ u64 EstimateRDTSCFrequency() {
const u64 timer_diff =
std::chrono::duration_cast<std::chrono::nanoseconds>(endTime - startTime).count();
const u64 tsc_diff = tscEnd - tscStart;
- const u64 tsc_freq = umuldiv64(tsc_diff, 1000000000ULL, timer_diff);
+ const u64 tsc_freq = MultiplyAndDivide64(tsc_diff, 1000000000ULL, timer_diff);
return tsc_freq;
}
@@ -100,27 +67,27 @@ u64 NativeClock::GetRTSC() {
std::chrono::nanoseconds NativeClock::GetTimeNS() {
const u64 rtsc_value = GetRTSC();
- return std::chrono::nanoseconds{umuldiv64(rtsc_value, 1000000000, rtsc_frequency)};
+ return std::chrono::nanoseconds{MultiplyAndDivide64(rtsc_value, 1000000000, rtsc_frequency)};
}
std::chrono::microseconds NativeClock::GetTimeUS() {
const u64 rtsc_value = GetRTSC();
- return std::chrono::microseconds{umuldiv64(rtsc_value, 1000000, rtsc_frequency)};
+ return std::chrono::microseconds{MultiplyAndDivide64(rtsc_value, 1000000, rtsc_frequency)};
}
std::chrono::milliseconds NativeClock::GetTimeMS() {
const u64 rtsc_value = GetRTSC();
- return std::chrono::milliseconds{umuldiv64(rtsc_value, 1000, rtsc_frequency)};
+ return std::chrono::milliseconds{MultiplyAndDivide64(rtsc_value, 1000, rtsc_frequency)};
}
u64 NativeClock::GetClockCycles() {
const u64 rtsc_value = GetRTSC();
- return umuldiv64(rtsc_value, emulated_clock_frequency, rtsc_frequency);
+ return MultiplyAndDivide64(rtsc_value, emulated_clock_frequency, rtsc_frequency);
}
u64 NativeClock::GetCPUCycles() {
const u64 rtsc_value = GetRTSC();
- return umuldiv64(rtsc_value, emulated_cpu_frequency, rtsc_frequency);
+ return MultiplyAndDivide64(rtsc_value, emulated_cpu_frequency, rtsc_frequency);
}
} // namespace X64
diff --git a/src/core/host_timing.cpp b/src/core/host_timing.cpp
index ef9977b76..4ccf7c6c1 100644
--- a/src/core/host_timing.cpp
+++ b/src/core/host_timing.cpp
@@ -36,8 +36,7 @@ struct CoreTiming::Event {
};
CoreTiming::CoreTiming() {
- Common::WallClock* wall = Common::CreateBestMatchingClock(Core::Timing::BASE_CLOCK_RATE, Core::Timing::CNTFREQ);
- clock = std::unique_ptr<Common::WallClock>(wall);
+ clock = Common::CreateBestMatchingClock(Core::Timing::BASE_CLOCK_RATE, Core::Timing::CNTFREQ);
}
CoreTiming::~CoreTiming() = default;