Skip to content

Commit 276c226

Browse files
committed
Restore comments
1 parent e0145e8 commit 276c226

9 files changed

Lines changed: 159 additions & 113 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ endif()
287287
if(CEMU_ARCHITECTURE MATCHES "(aarch64)|(AARCH64)|(arm64)|(ARM64)")
288288
add_subdirectory("dependencies/xbyak_aarch64" EXCLUDE_FROM_ALL)
289289
if(MSVC)
290-
set_target_properties(xbyak_aarch64 PROPERTIES COMPILE_FLAGS "/wd4245 /wd4458")
290+
target_compile_options(xbyak_aarch64 PRIVATE "/wd4245" "/wd4458")
291291
endif()
292292
endif()
293293

src/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,9 @@ cemu_use_precompiled_header(CemuBin)
7373
if(MSVC)
7474
set(CEMU_LINKER_FLAGS "/NODEFAULTLIB:MSVCRT")
7575

76-
# Check for the specific VS 17.10 version
7776
if(MSVC_VERSION EQUAL 1940)
77+
# workaround for an msvc issue on VS 17.10 where generated ILK files are too large
78+
# see https://developercommunity.visualstudio.com/t/After-updating-to-VS-1710-the-size-of-/10665511
7879
string(APPEND CEMU_LINKER_FLAGS " /INCREMENTAL:NO")
7980
endif()
8081

src/Cafe/CMakeLists.txt

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -664,10 +664,6 @@ target_link_libraries(CemuCafe PRIVATE
664664
OpenSSL::SSL
665665
)
666666

667-
if(MSVC AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64")
668-
target_link_libraries(CemuCafe PRIVATE ntdll.lib)
669-
endif()
670-
671667
if (ENABLE_WAYLAND)
672668
# PUBLIC because wayland-client.h is included in VulkanAPI.h
673669
target_link_libraries(CemuCafe PUBLIC Wayland::Client)
@@ -676,9 +672,7 @@ endif()
676672
if (ENABLE_LIBUSB)
677673
if (ENABLE_VCPKG)
678674
if(WIN32)
679-
if(DEFINED VCPKG_TARGET_TRIPLET)
680-
set(PKG_CONFIG_EXECUTABLE "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/tools/pkgconf/pkgconf.exe")
681-
endif()
675+
set(PKG_CONFIG_EXECUTABLE "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/tools/pkgconf/pkgconf.exe")
682676
endif()
683677
find_package(PkgConfig REQUIRED)
684678
pkg_check_modules(libusb REQUIRED IMPORTED_TARGET libusb-1.0)

src/Cafe/HW/Espresso/PPCTimer.cpp

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,14 @@
33
#include "util/helpers/fspinlock.h"
44
#include "util/highresolutiontimer/HighResolutionTimer.h"
55
#include "Common/cpu_features.h"
6+
67
#include "Common/Intrinsics.h"
78

9+
#include <chrono>
10+
#include <thread>
11+
812
uint64 _rdtscLastMeasure = 0;
913
uint64 _rdtscFrequency = 0;
10-
uint64 _tickSummary = 0;
11-
12-
struct uint128_t
13-
{
14-
uint64 low;
15-
uint64 high;
16-
};
17-
18-
static_assert(sizeof(uint128_t) == 16);
1914

2015
uint128_t _rdtscAcc{};
2116

@@ -30,32 +25,42 @@ uint64 muldiv64(uint64 a, uint64 b, uint64 d)
3025

3126
uint64 PPCTimer_estimateRDTSCFrequency()
3227
{
33-
#if defined(ARCH_X86_64)
28+
#if defined(ARCH_X86_64) || defined(__x86_64__) || defined(_M_X64)
3429
if (!g_CPUFeatures.x86.invariant_tsc)
3530
cemuLog_log(LogType::Force, "Invariant TSC not supported");
36-
#endif
31+
#endif
3732

3833
BARRIER_FENCE();
3934
uint64 tscStart = READ_TSC();
40-
unsigned int startTime = GetTickCount();
35+
auto startTime = std::chrono::steady_clock::now();
4136
HRTick startTick = HighResolutionTimer::now().getTick();
42-
37+
// wait roughly 3 seconds
4338
while (true)
4439
{
45-
if ((GetTickCount() - startTime) >= 3000)
40+
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
41+
std::chrono::steady_clock::now() - startTime).count();
42+
if (elapsed >= 3000)
4643
break;
4744
std::this_thread::sleep_for(std::chrono::milliseconds(10));
4845
}
4946

5047
BARRIER_FENCE();
5148
HRTick stopTick = HighResolutionTimer::now().getTick();
5249
uint64 tscEnd = READ_TSC();
53-
50+
// derive frequency approximation from measured time difference
5451
uint64 tsc_diff = tscEnd - tscStart;
5552
uint64 hrtFreq = 0;
5653
uint64 hrtDiff = HighResolutionTimer::getTimeDiffEx(startTick, stopTick, hrtFreq);
5754
uint64 tsc_freq = muldiv64(tsc_diff, hrtFreq, hrtDiff);
5855

56+
// uint64 freqMultiplier = tsc_freq / hrtFreq;
57+
//cemuLog_log(LogType::Force, "RDTSC measurement test:");
58+
//cemuLog_log(LogType::Force, "TSC-diff: 0x{:016x}", tsc_diff);
59+
//cemuLog_log(LogType::Force, "TSC-freq: 0x{:016x}", tsc_freq);
60+
//cemuLog_log(LogType::Force, "HPC-diff: 0x{:016x}", qpc_diff);
61+
//cemuLog_log(LogType::Force, "HPC-freq: 0x{:016x}", (uint64)qpc_freq.QuadPart);
62+
//cemuLog_log(LogType::Force, "Multiplier: 0x{:016x}", freqMultiplier);
63+
5964
return tsc_freq;
6065
}
6166

@@ -72,6 +77,8 @@ void PPCTimer_init()
7277
_rdtscLastMeasure = READ_TSC();
7378
}
7479

80+
uint64 _tickSummary = 0;
81+
7582
void PPCTimer_start()
7683
{
7784
_rdtscLastMeasure = READ_TSC();
@@ -91,12 +98,10 @@ uint64 PPCTimer_microsecondsToTsc(uint64 us)
9198
uint64 PPCTimer_tscToMicroseconds(uint64 us)
9299
{
93100
uint128_t r{};
94-
// Changed: Using Multiply64to128 wrapper
95-
r.low = Multiply64to128(us, 1000000ULL, &r.high);
101+
r.low = portable_umul128(us, 1000000ULL, &r.high);
96102

97103
uint64 remainder;
98-
// Changed: Using Divide128by64 wrapper
99-
const uint64 microseconds = Divide128by64(r.high, r.low, _rdtscFrequency, &remainder);
104+
const uint64 microseconds = portable_udiv128(r.high, r.low, _rdtscFrequency, &remainder);
100105

101106
return microseconds;
102107
}
@@ -113,37 +118,35 @@ void PPCTimer_waitForInit()
113118

114119
FSpinlock sTimerSpinlock;
115120

121+
// thread safe
116122
uint64 PPCTimer_getFromRDTSC()
117123
{
118124
sTimerSpinlock.lock();
119125
BARRIER_FENCE();
120126
uint64 rdtscCurrentMeasure = READ_TSC();
121127
uint64 rdtscDif = rdtscCurrentMeasure - _rdtscLastMeasure;
122-
128+
// optimized max(rdtscDif, 0) without conditionals
123129
rdtscDif = rdtscDif & ~(uint64)((sint64)rdtscDif >> 63);
124130

125131
uint128_t diff{};
126-
diff.low = Multiply64to128(rdtscDif, Espresso::CORE_CLOCK, &diff.high);
132+
diff.low = portable_umul128(rdtscDif, Espresso::CORE_CLOCK, &diff.high);
127133

128134
if(rdtscCurrentMeasure > _rdtscLastMeasure)
129-
_rdtscLastMeasure = rdtscCurrentMeasure;
135+
_rdtscLastMeasure = rdtscCurrentMeasure; // only travel forward in time
130136

131-
uint8 c = 0;
132-
#if defined(_MSC_VER)
133-
c = _addcarry_u64(c, _rdtscAcc.low, diff.low, &_rdtscAcc.low);
134-
_addcarry_u64(c, _rdtscAcc.high, diff.high, &_rdtscAcc.high);
135-
#else
136-
c = _addcarry_u64(c, _rdtscAcc.low, diff.low, (unsigned long long*)&_rdtscAcc.low);
137-
_addcarry_u64(c, _rdtscAcc.high, diff.high, (unsigned long long*)&_rdtscAcc.high);
138-
#endif
137+
uint64 old_low = _rdtscAcc.low;
138+
_rdtscAcc.low += diff.low;
139+
uint64 carry = (_rdtscAcc.low < old_low) ? 1 : 0;
140+
_rdtscAcc.high += diff.high + carry;
139141

140142
uint64 remainder;
141-
uint64 elapsedTick = Divide128by64(_rdtscAcc.high, _rdtscAcc.low, _rdtscFrequency, &remainder);
143+
uint64 elapsedTick = portable_udiv128(_rdtscAcc.high, _rdtscAcc.low, _rdtscFrequency, &remainder);
142144

143145
_rdtscAcc.low = remainder;
144146
_rdtscAcc.high = 0;
145147

146-
elapsedTick <<= 3ull;
148+
// timer scaling
149+
elapsedTick <<= 3ull; // *8
147150
uint8 timerShiftFactor = ActiveSettings::GetTimerShiftFactor();
148151
elapsedTick >>= timerShiftFactor;
149152

src/Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,7 @@ struct IMLInstruction
758758
void make_fpr_compare(IMLReg regA, IMLReg regB, IMLReg regR, IMLCondition cond)
759759
{
760760
this->type = PPCREC_IML_TYPE_FPR_COMPARE;
761-
this->operation = 255;
761+
this->operation = -999;
762762
this->op_fpr_compare.regR = regR;
763763
this->op_fpr_compare.regA = regA;
764764
this->op_fpr_compare.regB = regB;
@@ -807,7 +807,7 @@ struct IMLInstruction
807807
void make_x86_eflags_jcc(IMLCondition cond, bool invertedCondition)
808808
{
809809
this->type = PPCREC_IML_TYPE_X86_EFLAGS_JCC;
810-
this->operation = 255;
810+
this->operation = -999;
811811
this->op_x86_eflags_jcc.cond = cond;
812812
this->op_x86_eflags_jcc.invertedCondition = invertedCondition;
813813
}

src/Common/Intrinsics.h

Lines changed: 80 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,101 @@
11
#pragma once
2+
23
#include <cstdint>
34

4-
#if defined(_MSC_VER)
5-
#include <intrin.h>
6-
#if defined(_M_ARM64)
7-
#include <arm64intr.h>
8-
#define BARRIER_FENCE() __dmb(_ARM64_BARRIER_ISH)
9-
#define READ_TSC() _ReadStatusReg(ARM64_CNTVCT_EL0)
10-
#else
5+
using uint64 = uint64_t;
6+
using sint64 = int64_t;
7+
using uint8 = uint8_t;
8+
9+
#if defined(_M_X64) || defined(__x86_64__)
10+
#if defined(_MSC_VER)
1111
#include <immintrin.h>
12+
#pragma intrinsic(__rdtsc)
1213
#define BARRIER_FENCE() _mm_mfence()
1314
#define READ_TSC() __rdtsc()
14-
#endif
15-
#else
16-
#if defined(__aarch64__)
17-
#define BARRIER_FENCE() __asm__ __volatile__ ("dmb ish" : : : "memory")
18-
static inline uint64_t READ_TSC() {
19-
uint64_t val;
20-
__asm__ __volatile__("mrs %0, cntvct_el0" : "=r" (val));
21-
return val;
22-
}
23-
#else
15+
#else
2416
#include <x86intrin.h>
25-
#define BARRIER_FENCE() __asm__ __volatile__ ("mfence" : : : "memory")
17+
#define BARRIER_FENCE() __builtin_ia32_mfence()
2618
#define READ_TSC() __rdtsc()
2719
#endif
20+
#elif defined(_M_ARM64) || defined(__aarch64__)
21+
#if defined(_MSC_VER)
22+
#include <intrin.h>
23+
#define BARRIER_FENCE() __dmb(_ARM64_BARRIER_SY)
24+
#define READ_TSC() _ReadStatusReg(ARM64_CNTVCT_EL0)
25+
#else
26+
#define BARRIER_FENCE() __asm__ __volatile__("dmb sy" : : : "memory")
27+
inline uint64 READ_TSC() {
28+
uint64 virtual_timer;
29+
__asm__ __volatile__("mrs %0, cntvct_el0" : "=r" (virtual_timer));
30+
return virtual_timer;
31+
}
32+
#endif
2833
#endif
2934

30-
static inline uint64_t Multiply64to128(uint64_t a, uint64_t b, uint64_t* high) {
31-
#if defined(__SIZEOF_INT128__)
32-
unsigned __int128 res = (unsigned __int128)a * b;
33-
*high = (uint64_t)(res >> 64);
34-
return (uint64_t)res;
35-
#elif defined(_MSC_VER) && defined(_M_X64)
36-
return _umul128(a, b, high);
37-
#elif defined(_MSC_VER) && defined(_M_ARM64)
38-
*high = __umulh(a, b);
39-
return a * b;
35+
struct uint128_t {
36+
uint64 low;
37+
uint64 high;
38+
};
39+
40+
inline uint64 portable_umul128(uint64 multiplier, uint64 multiplicand, uint64* high) {
41+
#if defined(_MSC_VER)
42+
#if defined(_M_X64)
43+
return _umul128(multiplier, multiplicand, high);
44+
#elif defined(_M_ARM64)
45+
*high = __umulh(multiplier, multiplicand);
46+
return multiplier * multiplicand;
47+
#endif
4048
#else
41-
// Generic fallback for other compilers/archs
42-
uint64_t a_lo = (uint32_t)a, a_hi = a >> 32;
43-
uint64_t b_lo = (uint32_t)b, b_hi = b >> 32;
44-
uint64_t p0 = a_lo * b_lo;
45-
uint64_t p1 = a_lo * b_hi;
46-
uint64_t p2 = a_hi * b_lo;
47-
uint64_t p3 = a_hi * b_hi;
48-
uint64_t cy = (uint32_t)(p0 >> 32) + (uint32_t)p1 + (uint32_t)p2;
49-
*high = p3 + (p1 >> 32) + (p2 >> 32) + (cy >> 32);
50-
return (p0 & 0xFFFFFFFF) | (cy << 32);
49+
unsigned __int128 res = (unsigned __int128)multiplier * multiplicand;
50+
*high = (uint64)(res >> 64);
51+
return (uint64)res;
5152
#endif
5253
}
5354

54-
static inline uint64_t Divide128by64(uint64_t high, uint64_t low, uint64_t divisor, uint64_t* remainder) {
55-
#if defined(__SIZEOF_INT128__)
56-
unsigned __int128 dividend = ((unsigned __int128)high << 64) | low;
57-
*remainder = (uint64_t)(dividend % divisor);
58-
return (uint64_t)(dividend / divisor);
59-
#elif defined(_MSC_VER) && defined(_M_X64)
60-
return _udiv128(high, low, divisor, remainder);
61-
#else
62-
// Software fallback for MSVC ARM64 and others
63-
// This implements long division for 128-bit / 64-bit
64-
if (high < divisor) {
65-
// Common case for many emulators: quotient fits in 64 bits
66-
uint64_t q, r;
67-
// Schoolbook division: split 128-bit into 4x32-bit if necessary,
68-
// but here we use a binary long division for simplicity and correctness.
69-
uint64_t rem = high;
70-
uint64_t quot = 0;
55+
inline uint64 portable_udiv128(uint64 high, uint64 low, uint64 denominator, uint64* remainder) {
56+
#if defined(_MSC_VER)
57+
#if defined(_M_X64)
58+
return _udiv128(high, low, denominator, remainder);
59+
#else
60+
if (high == 0) {
61+
if (remainder) *remainder = low % denominator;
62+
return low / denominator;
63+
}
64+
65+
uint64 rem = 0;
66+
uint64 quot = 0;
67+
for (int i = 63; i >= 0; i--) {
68+
rem = (rem << 1) | (high >> 63);
69+
high <<= 1;
70+
if (rem >= denominator) {
71+
rem -= denominator;
72+
quot |= (1ULL << i);
73+
}
74+
}
7175
for (int i = 63; i >= 0; i--) {
72-
rem = (rem << 1) | ((low >> i) & 1);
73-
if (rem >= divisor) {
74-
rem -= divisor;
76+
rem = (rem << 1) | (low >> 63);
77+
low <<= 1;
78+
if (rem >= denominator) {
79+
rem -= denominator;
7580
quot |= (1ULL << i);
7681
}
7782
}
78-
*remainder = rem;
79-
return quot;
80-
} else {
81-
// Quotient overflow: high >= divisor means result > 64 bits.
82-
// If your code expects a 64-bit return, this is technically an error state.
83-
// Return max value as a sentinel or handle as needed.
84-
*remainder = 0;
85-
return 0xFFFFFFFFFFFFFFFFULL;
86-
}
83+
// Secure native software fallback block
84+
uint64_t q = 0;
85+
uint64_t r = 0;
86+
for (int i = 127; i >= 0; i--) {
87+
r = (r << 1) | ((i >= 64 ? high >> (i - 64) : low >> i) & 1);
88+
if (r >= denominator) {
89+
r -= denominator;
90+
q |= (1ULL << (i % 64));
91+
}
92+
}
93+
if (remainder) *remainder = r;
94+
return q;
95+
#endif
96+
#else
97+
unsigned __int128 dividend = ((unsigned __int128)high << 64) | low;
98+
if (remainder) *remainder = (uint64)(dividend % denominator);
99+
return (uint64)(dividend / denominator);
87100
#endif
88101
}

src/Common/precompiled.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -394,12 +394,15 @@ inline void _mm_mfence()
394394

395395
inline unsigned char _addcarry_u64(unsigned char carry, unsigned long long a, unsigned long long b, unsigned long long *result)
396396
{
397+
#if !defined(_MSC_VER)
397398
unsigned __int128 res = (unsigned __int128)a + b + carry;
398399
*result = (unsigned long long)res;
399400
return (res >> 64) ? 1 : 0;
400-
}
401-
401+
#else
402+
*result = a + b + carry;
403+
return (*result < a || (*result == a && carry > 0)) ? 1 : 0;
402404
#endif
405+
}
403406

404407
// asserts
405408

0 commit comments

Comments
 (0)