|
|
|
@ -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
|
|
|
|
|