summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/uint128.cpp24
-rw-r--r--src/common/uint128.h23
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.cpp2
-rw-r--r--src/core/core_timing_util.cpp8
-rw-r--r--src/core/core_timing_util.h2
5 files changed, 32 insertions, 27 deletions
diff --git a/src/common/uint128.cpp b/src/common/uint128.cpp
index aea7f03e2..8548ba808 100644
--- a/src/common/uint128.cpp
+++ b/src/common/uint128.cpp
@@ -1,7 +1,25 @@
1#ifdef _MSC_VER
2#include <intrin.h>
3
4#pragma intrinsic(_umul128)
5#endif
6#include "common/uint128.h"
1 7
2namespace Common { 8namespace Common {
9u128 Multiply64Into128(u64 a, u64 b) {
10#ifdef _MSC_VER
11 u128 result;
12 result[0] = _umul128(a, b, &result[1]);
13#else
14 unsigned __int128 tmp = a;
15 tmp *= b;
16 u128 result;
17 std::memcpy(&result, &tmp, sizeof(u128));
18#endif
19 return result;
20}
3 21
4std::pair<u64, u64> udiv128(u128 dividend, u64 divisor) { 22std::pair<u64, u64> Divide128On64(u128 dividend, u64 divisor) {
5 u64 remainder = dividend[0] % divisor; 23 u64 remainder = dividend[0] % divisor;
6 u64 accum = dividend[0] / divisor; 24 u64 accum = dividend[0] / divisor;
7 if (dividend[1] == 0) 25 if (dividend[1] == 0)
@@ -12,6 +30,10 @@ std::pair<u64, u64> udiv128(u128 dividend, u64 divisor) {
12 u64 second_segment = (first_segment % divisor) << 32; 30 u64 second_segment = (first_segment % divisor) << 32;
13 accum += (second_segment / divisor); 31 accum += (second_segment / divisor);
14 remainder += second_segment % divisor; 32 remainder += second_segment % divisor;
33 if (remainder >= divisor) {
34 accum++;
35 remainder -= divisor;
36 }
15 return {accum, remainder}; 37 return {accum, remainder};
16} 38}
17 39
diff --git a/src/common/uint128.h b/src/common/uint128.h
index fda313bcc..45e384c33 100644
--- a/src/common/uint128.h
+++ b/src/common/uint128.h
@@ -1,30 +1,13 @@
1#include <array> 1#include <array>
2#include <cstdint> 2#include <cstdint>
3#include <utility>
4#include <cstring> 3#include <cstring>
4#include <utility>
5#include "common/common_types.h" 5#include "common/common_types.h"
6 6
7namespace Common { 7namespace Common {
8 8
9#ifdef _MSC_VER 9u128 Multiply64Into128(u64 a, u64 b);
10#include <intrin.h>
11
12#pragma intrinsic(_umul128)
13#endif
14
15inline u128 umul128(u64 a, u64 b) {
16#ifdef _MSC_VER
17u128 result;
18result[0] = _umul128(a, b, &result[1]);
19#else
20unsigned __int128 tmp = a;
21tmp *= b;
22u128 result;
23std::memcpy(&result, &tmp, sizeof(u128));
24#endif
25return result;
26}
27 10
28std::pair<u64, u64> udiv128(u128 dividend, u64 divisor); 11std::pair<u64, u64> Divide128On64(u128 dividend, u64 divisor);
29 12
30} // namespace Common 13} // namespace Common
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp
index d36538257..25f76259b 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic.cpp
@@ -120,7 +120,7 @@ public:
120 return std::max(parent.core_timing.GetDowncount(), 0); 120 return std::max(parent.core_timing.GetDowncount(), 0);
121 } 121 }
122 u64 GetCNTPCT() override { 122 u64 GetCNTPCT() override {
123 return CpuCyclesToClockCycles(parent.core_timing.GetTicks()); 123 return Timing::CpuCyclesToClockCycles(parent.core_timing.GetTicks());
124 } 124 }
125 125
126 ARM_Dynarmic& parent; 126 ARM_Dynarmic& parent;
diff --git a/src/core/core_timing_util.cpp b/src/core/core_timing_util.cpp
index 8fc92560a..aab4aa697 100644
--- a/src/core/core_timing_util.cpp
+++ b/src/core/core_timing_util.cpp
@@ -7,6 +7,7 @@
7#include <cinttypes> 7#include <cinttypes>
8#include <limits> 8#include <limits>
9#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "common/uint128.h"
10 11
11namespace Core::Timing { 12namespace Core::Timing {
12 13
@@ -61,10 +62,9 @@ s64 nsToCycles(u64 ns) {
61} 62}
62 63
63u64 CpuCyclesToClockCycles(u64 ticks) { 64u64 CpuCyclesToClockCycles(u64 ticks) {
64 u64 result = ticks; 65 u128 temporal = Common::Multiply64Into128(ticks, CNTFREQ);
65 result *= CNTFREQ; 66 std::pair<u64, u64> result = Common::Divide128On64(temporal, BASE_CLOCK_RATE);
66 result /= BASE_CLOCK_RATE; 67 return result.first;
67 return static_cast<u64>(result);
68} 68}
69 69
70} // namespace Core::Timing 70} // namespace Core::Timing
diff --git a/src/core/core_timing_util.h b/src/core/core_timing_util.h
index 545d3a260..679aa3123 100644
--- a/src/core/core_timing_util.h
+++ b/src/core/core_timing_util.h
@@ -11,7 +11,7 @@ namespace Core::Timing {
11// The below clock rate is based on Switch's clockspeed being widely known as 1.020GHz 11// The below clock rate is based on Switch's clockspeed being widely known as 1.020GHz
12// The exact value used is of course unverified. 12// The exact value used is of course unverified.
13constexpr u64 BASE_CLOCK_RATE = 1019215872; // Switch clock speed is 1020MHz un/docked 13constexpr u64 BASE_CLOCK_RATE = 1019215872; // Switch clock speed is 1020MHz un/docked
14constexpr u64 CNTFREQ = 19200000; // Value from fusee. 14constexpr u64 CNTFREQ = 19200000; // Value from fusee.
15 15
16inline s64 msToCycles(int ms) { 16inline s64 msToCycles(int ms) {
17 // since ms is int there is no way to overflow 17 // since ms is int there is no way to overflow