21 #include <winpr/config.h>
23 #include <winpr/assert.h>
24 #include <winpr/sysinfo.h>
25 #include <winpr/platform.h>
28 #include "cpufeatures/cpu-features.h"
31 #if defined(__linux__)
32 #include <sys/types.h>
38 #if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 199309L)
40 #elif !defined(__APPLE__)
42 #include <sys/sysinfo.h>
47 #define TAG WINPR_TAG("sysinfo")
49 #define FILETIME_TO_UNIX_OFFSET_S 11644473600UL
51 #if defined(__MACH__) && defined(__APPLE__)
53 #include <mach/mach_time.h>
55 static UINT64 scaleHighPrecision(UINT64 i, UINT32 numer, UINT32 denom)
57 UINT64 high = (i >> 32) * numer;
58 UINT64 low = (i & 0xffffffffull) * numer / denom;
59 UINT64 highRem = ((high % denom) << 32) / denom;
61 return (high << 32) + highRem + low;
64 static UINT64 mac_get_time_ns(
void)
66 mach_timebase_info_data_t timebase = { 0 };
67 mach_timebase_info(&timebase);
68 UINT64 t = mach_absolute_time();
69 return scaleHighPrecision(t, timebase.numer, timebase.denom);
99 #ifdef WINPR_HAVE_UNISTD_H
103 #include <winpr/crt.h>
104 #include <winpr/platform.h>
106 #if defined(__MACOSX__) || defined(__IOS__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
107 defined(__OpenBSD__) || defined(__DragonFly__)
108 #include <sys/sysctl.h>
111 static WORD GetProcessorArchitecture(
void)
113 WORD cpuArch = PROCESSOR_ARCHITECTURE_UNKNOWN;
115 AndroidCpuFamily family = android_getCpuFamily();
119 case ANDROID_CPU_FAMILY_ARM:
120 return PROCESSOR_ARCHITECTURE_ARM;
122 case ANDROID_CPU_FAMILY_X86:
123 return PROCESSOR_ARCHITECTURE_INTEL;
125 case ANDROID_CPU_FAMILY_MIPS:
126 return PROCESSOR_ARCHITECTURE_MIPS;
128 case ANDROID_CPU_FAMILY_ARM64:
129 return PROCESSOR_ARCHITECTURE_ARM64;
131 case ANDROID_CPU_FAMILY_X86_64:
132 return PROCESSOR_ARCHITECTURE_AMD64;
134 case ANDROID_CPU_FAMILY_MIPS64:
135 return PROCESSOR_ARCHITECTURE_MIPS64;
138 return PROCESSOR_ARCHITECTURE_UNKNOWN;
141 #elif defined(_M_ARM)
142 cpuArch = PROCESSOR_ARCHITECTURE_ARM;
143 #elif defined(_M_IX86)
144 cpuArch = PROCESSOR_ARCHITECTURE_INTEL;
145 #elif defined(_M_MIPS64)
147 cpuArch = PROCESSOR_ARCHITECTURE_MIPS64;
148 #elif defined(_M_MIPS)
149 cpuArch = PROCESSOR_ARCHITECTURE_MIPS;
150 #elif defined(_M_ARM64)
151 cpuArch = PROCESSOR_ARCHITECTURE_ARM64;
152 #elif defined(_M_AMD64)
153 cpuArch = PROCESSOR_ARCHITECTURE_AMD64;
154 #elif defined(_M_PPC)
155 cpuArch = PROCESSOR_ARCHITECTURE_PPC;
156 #elif defined(_M_ALPHA)
157 cpuArch = PROCESSOR_ARCHITECTURE_ALPHA;
158 #elif defined(_M_E2K)
159 cpuArch = PROCESSOR_ARCHITECTURE_E2K;
164 static DWORD GetNumberOfProcessors(
void)
168 return android_getCpuCount();
170 #elif defined(__linux__) || defined(__sun) || defined(_AIX)
171 numCPUs = (DWORD)sysconf(_SC_NPROCESSORS_ONLN);
172 #elif defined(__MACOSX__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
173 defined(__OpenBSD__) || defined(__DragonFly__)
176 size_t length =
sizeof(numCPUs);
178 #if defined(__FreeBSD__) || defined(__OpenBSD__)
181 mib[1] = HW_AVAILCPU;
183 sysctl(mib, 2, &numCPUs, &length, NULL, 0);
188 sysctl(mib, 2, &numCPUs, &length, NULL, 0);
194 #elif defined(__hpux)
195 numCPUs = (DWORD)mpctl(MPC_GETNUMSPUS, NULL, NULL);
197 numCPUs = (DWORD)sysconf(_SC_NPROC_ONLN);
202 static DWORD GetSystemPageSize(
void)
204 DWORD dwPageSize = 0;
205 long sc_page_size = -1;
206 #if defined(_SC_PAGESIZE)
208 if (sc_page_size < 0)
209 sc_page_size = sysconf(_SC_PAGESIZE);
212 #if defined(_SC_PAGE_SIZE)
214 if (sc_page_size < 0)
215 sc_page_size = sysconf(_SC_PAGE_SIZE);
219 if (sc_page_size > 0)
220 dwPageSize = (DWORD)sc_page_size;
222 if (dwPageSize < 4096)
231 WINPR_ASSERT(lpSystemInfo);
233 *lpSystemInfo = empty;
234 lpSystemInfo->DUMMYUNIONNAME.DUMMYSTRUCTNAME.wProcessorArchitecture =
235 GetProcessorArchitecture();
236 lpSystemInfo->dwPageSize = GetSystemPageSize();
237 lpSystemInfo->dwNumberOfProcessors = GetNumberOfProcessors();
242 GetSystemInfo(lpSystemInfo);
245 void GetSystemTime(LPSYSTEMTIME lpSystemTime)
249 struct tm* stm = NULL;
250 WORD wMilliseconds = 0;
252 wMilliseconds = (WORD)(GetTickCount() % 1000);
253 stm = gmtime_r(&ct, &tres);
258 lpSystemTime->wYear = (WORD)(stm->tm_year + 1900);
259 lpSystemTime->wMonth = (WORD)(stm->tm_mon + 1);
260 lpSystemTime->wDayOfWeek = (WORD)stm->tm_wday;
261 lpSystemTime->wDay = (WORD)stm->tm_mday;
262 lpSystemTime->wHour = (WORD)stm->tm_hour;
263 lpSystemTime->wMinute = (WORD)stm->tm_min;
264 lpSystemTime->wSecond = (WORD)stm->tm_sec;
265 lpSystemTime->wMilliseconds = wMilliseconds;
269 BOOL SetSystemTime(CONST
SYSTEMTIME* lpSystemTime)
275 VOID GetLocalTime(LPSYSTEMTIME lpSystemTime)
279 struct tm* ltm = NULL;
280 WORD wMilliseconds = 0;
282 wMilliseconds = (WORD)(GetTickCount() % 1000);
283 ltm = localtime_r(&ct, &tres);
288 lpSystemTime->wYear = (WORD)(ltm->tm_year + 1900);
289 lpSystemTime->wMonth = (WORD)(ltm->tm_mon + 1);
290 lpSystemTime->wDayOfWeek = (WORD)ltm->tm_wday;
291 lpSystemTime->wDay = (WORD)ltm->tm_mday;
292 lpSystemTime->wHour = (WORD)ltm->tm_hour;
293 lpSystemTime->wMinute = (WORD)ltm->tm_min;
294 lpSystemTime->wSecond = (WORD)ltm->tm_sec;
295 lpSystemTime->wMilliseconds = wMilliseconds;
299 BOOL SetLocalTime(CONST
SYSTEMTIME* lpSystemTime)
305 VOID GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime)
313 t.u64 = (winpr_GetUnixTimeNS() / 100ull) + FILETIME_TO_UNIX_OFFSET_S * 10000000ull;
314 *lpSystemTimeAsFileTime = t.ft;
317 BOOL GetSystemTimeAdjustment(PDWORD lpTimeAdjustment, PDWORD lpTimeIncrement,
318 PBOOL lpTimeAdjustmentDisabled)
324 #ifndef CLOCK_MONOTONIC_RAW
325 #define CLOCK_MONOTONIC_RAW 4
328 DWORD GetTickCount(
void)
330 return (DWORD)GetTickCount64();
334 #if !defined(_WIN32) || defined(_UWP)
336 #if defined(WITH_WINPR_DEPRECATED)
341 BOOL GetVersionExA(LPOSVERSIONINFOA lpVersionInformation)
346 if ((lpVersionInformation->dwOSVersionInfoSize ==
sizeof(OSVERSIONINFOA)) ||
347 (lpVersionInformation->dwOSVersionInfoSize ==
sizeof(OSVERSIONINFOEXA)))
349 lpVersionInformation->dwMajorVersion = 10;
350 lpVersionInformation->dwMinorVersion = 0;
351 lpVersionInformation->dwBuildNumber = 0;
352 lpVersionInformation->dwPlatformId = VER_PLATFORM_WIN32_NT;
353 ZeroMemory(lpVersionInformation->szCSDVersion,
sizeof(lpVersionInformation->szCSDVersion));
355 if (lpVersionInformation->dwOSVersionInfoSize ==
sizeof(OSVERSIONINFOEXA))
357 LPOSVERSIONINFOEXA lpVersionInformationEx = (LPOSVERSIONINFOEXA)lpVersionInformation;
358 lpVersionInformationEx->wServicePackMajor = 0;
359 lpVersionInformationEx->wServicePackMinor = 0;
360 lpVersionInformationEx->wSuiteMask = 0;
361 lpVersionInformationEx->wProductType = VER_NT_WORKSTATION;
362 lpVersionInformationEx->wReserved = 0;
371 if ((lpVersionInformation->dwOSVersionInfoSize ==
sizeof(OSVERSIONINFOA)) ||
372 (lpVersionInformation->dwOSVersionInfoSize ==
sizeof(OSVERSIONINFOEXA)))
374 lpVersionInformation->dwMajorVersion = 6;
375 lpVersionInformation->dwMinorVersion = 1;
376 lpVersionInformation->dwBuildNumber = 7601;
377 lpVersionInformation->dwPlatformId = VER_PLATFORM_WIN32_NT;
378 ZeroMemory(lpVersionInformation->szCSDVersion,
sizeof(lpVersionInformation->szCSDVersion));
380 if (lpVersionInformation->dwOSVersionInfoSize ==
sizeof(OSVERSIONINFOEXA))
382 LPOSVERSIONINFOEXA lpVersionInformationEx = (LPOSVERSIONINFOEXA)lpVersionInformation;
383 lpVersionInformationEx->wServicePackMajor = 1;
384 lpVersionInformationEx->wServicePackMinor = 0;
385 lpVersionInformationEx->wSuiteMask = 0;
386 lpVersionInformationEx->wProductType = VER_NT_WORKSTATION;
387 lpVersionInformationEx->wReserved = 0;
397 BOOL GetVersionExW(LPOSVERSIONINFOW lpVersionInformation)
399 ZeroMemory(lpVersionInformation->szCSDVersion,
sizeof(lpVersionInformation->szCSDVersion));
400 return GetVersionExA((LPOSVERSIONINFOA)lpVersionInformation);
407 #if !defined(_WIN32) || defined(_UWP)
409 BOOL GetComputerNameW(LPWSTR lpBuffer, LPDWORD lpnSize)
413 if (!lpnSize || (*lpnSize > INT_MAX))
418 buffer = malloc(*lpnSize);
422 rc = GetComputerNameA(buffer, lpnSize);
424 if (rc && (*lpnSize > 0))
426 const SSIZE_T res = ConvertUtf8NToWChar(buffer, *lpnSize, lpBuffer, *lpnSize);
435 BOOL GetComputerNameA(LPSTR lpBuffer, LPDWORD lpnSize)
439 SetLastError(ERROR_BAD_ARGUMENTS);
443 char hostname[256 + 1] = { 0 };
444 if (gethostname(hostname, ARRAYSIZE(hostname) - 1) == -1)
447 size_t length = strnlen(hostname, MAX_COMPUTERNAME_LENGTH);
448 const char* dot = strchr(hostname,
'.');
450 length = WINPR_ASSERTING_INT_CAST(
size_t, (dot - hostname));
452 if ((*lpnSize <= (DWORD)length) || !lpBuffer)
454 SetLastError(ERROR_BUFFER_OVERFLOW);
455 *lpnSize = (DWORD)(length + 1);
459 strncpy(lpBuffer, hostname, length);
460 lpBuffer[length] =
'\0';
461 *lpnSize = (DWORD)length;
465 BOOL GetComputerNameExA(COMPUTER_NAME_FORMAT NameType, LPSTR lpBuffer, LPDWORD lpnSize)
468 char hostname[256] = { 0 };
472 SetLastError(ERROR_BAD_ARGUMENTS);
476 if ((NameType == ComputerNameNetBIOS) || (NameType == ComputerNamePhysicalNetBIOS))
478 BOOL rc = GetComputerNameA(lpBuffer, lpnSize);
482 if (GetLastError() == ERROR_BUFFER_OVERFLOW)
483 SetLastError(ERROR_MORE_DATA);
489 if (gethostname(hostname,
sizeof(hostname)) == -1)
492 length = strnlen(hostname,
sizeof(hostname));
496 case ComputerNameDnsHostname:
497 case ComputerNameDnsDomain:
498 case ComputerNameDnsFullyQualified:
499 case ComputerNamePhysicalDnsHostname:
500 case ComputerNamePhysicalDnsDomain:
501 case ComputerNamePhysicalDnsFullyQualified:
502 if ((*lpnSize <= (DWORD)length) || !lpBuffer)
504 *lpnSize = (DWORD)(length + 1);
505 SetLastError(ERROR_MORE_DATA);
509 CopyMemory(lpBuffer, hostname, length);
510 lpBuffer[length] =
'\0';
511 *lpnSize = (DWORD)length;
521 BOOL GetComputerNameExW(COMPUTER_NAME_FORMAT NameType, LPWSTR lpBuffer, LPDWORD lpnSize)
524 LPSTR lpABuffer = NULL;
528 SetLastError(ERROR_BAD_ARGUMENTS);
534 lpABuffer = calloc(*lpnSize,
sizeof(CHAR));
540 rc = GetComputerNameExA(NameType, lpABuffer, lpnSize);
542 if (rc && (*lpnSize > 0))
544 const SSIZE_T res = ConvertUtf8NToWChar(lpABuffer, *lpnSize, lpBuffer, *lpnSize);
556 DWORD GetTickCount(
void)
558 return (DWORD)GetTickCount64();
563 #if (!defined(_WIN32)) || (defined(_WIN32) && (_WIN32_WINNT < 0x0600))
565 ULONGLONG winpr_GetTickCount64(
void)
567 const UINT64 ns = winpr_GetTickCount64NS();
568 return WINPR_TIME_NS_TO_MS(ns);
573 UINT64 winpr_GetTickCount64NS(
void)
576 #if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 199309L)
577 struct timespec ts = { 0 };
579 if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) == 0)
580 ticks = (WINPR_ASSERTING_INT_CAST(uint64_t, ts.tv_sec) * 1000000000ull) +
581 WINPR_ASSERTING_INT_CAST(uint64_t, ts.tv_nsec);
582 #elif defined(__MACH__) && defined(__APPLE__)
583 ticks = mac_get_time_ns();
584 #elif defined(_WIN32)
587 if (QueryPerformanceFrequency(&freq) && QueryPerformanceCounter(&li))
588 ticks = li.QuadPart * 1000000000ull / freq.QuadPart;
590 struct timeval tv = { 0 };
592 if (gettimeofday(&tv, NULL) == 0)
593 ticks = (tv.tv_sec * 1000000000ull) + (tv.tv_usec * 1000ull);
602 static UINT64 first = 0;
603 static UINT64 uptime = 0;
606 struct sysinfo info = { 0 };
607 if (sysinfo(&info) == 0)
610 uptime = 1000000000ull * info.uptime;
614 ticks = ticks - first + uptime;
619 UINT64 winpr_GetUnixTimeNS(
void)
628 GetSystemTimeAsFileTime(&t.ft);
629 return (t.u64 - FILETIME_TO_UNIX_OFFSET_S * 10000000ull) * 100ull;
630 #elif defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 199309L)
631 struct timespec ts = { 0 };
632 if (clock_gettime(CLOCK_REALTIME, &ts) != 0)
634 return WINPR_ASSERTING_INT_CAST(uint64_t, ts.tv_sec) * 1000000000ull +
635 WINPR_ASSERTING_INT_CAST(uint64_t, ts.tv_nsec);
637 struct timeval tv = { 0 };
638 if (gettimeofday(&tv, NULL) != 0)
640 return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000ull;
647 #if defined(__GNUC__)
648 #define xgetbv(_func_, _lo_, _hi_) \
649 __asm__ __volatile__("xgetbv" : "=a"(_lo_), "=d"(_hi_) : "c"(_func_))
650 #elif defined(_MSC_VER)
651 #define xgetbv(_func_, _lo_, _hi_) \
653 unsigned __int64 val = _xgetbv(_func_); \
654 _lo_ = val & 0xFFFFFFFF; \
655 _hi_ = (val >> 32); \
659 #define B_BIT_AVX2 (1 << 5)
660 #define B_BIT_AVX512F (1 << 16)
661 #define D_BIT_MMX (1 << 23)
662 #define D_BIT_SSE (1 << 25)
663 #define D_BIT_SSE2 (1 << 26)
664 #define D_BIT_3DN (1 << 30)
665 #define C_BIT_SSE3 (1 << 0)
666 #define C_BIT_PCLMULQDQ (1 << 1)
667 #define C81_BIT_LZCNT (1 << 5)
668 #define C_BIT_3DNP (1 << 8)
669 #define C_BIT_3DNP (1 << 8)
670 #define C_BIT_SSSE3 (1 << 9)
671 #define C_BIT_SSE41 (1 << 19)
672 #define C_BIT_SSE42 (1 << 20)
673 #define C_BIT_FMA (1 << 12)
674 #define C_BIT_AES (1 << 25)
675 #define C_BIT_XGETBV (1 << 27)
676 #define C_BIT_AVX (1 << 28)
677 #define E_BIT_XMM (1 << 1)
678 #define E_BIT_YMM (1 << 2)
679 #define E_BITS_AVX (E_BIT_XMM | E_BIT_YMM)
681 static void cpuid(
unsigned info,
unsigned* eax,
unsigned* ebx,
unsigned* ecx,
unsigned* edx)
684 *eax = *ebx = *ecx = *edx = 0;
698 :
"=a"(*eax),
"=S"(*ebx),
"=c"(*ecx),
"=d"(*edx)
699 :
"a"(info),
"c"(0));
700 #elif defined(_MSC_VER)
709 #elif defined(_M_ARM) || defined(_M_ARM64)
710 #if defined(__linux__)
712 #define HWCAP_SWP (1 << 0)
713 #define HWCAP_HALF (1 << 1)
714 #define HWCAP_THUMB (1 << 2)
715 #define HWCAP_26BIT (1 << 3)
716 #define HWCAP_FAST_MULT (1 << 4)
717 #define HWCAP_FPA (1 << 5)
718 #define HWCAP_VFP (1 << 6)
719 #define HWCAP_EDSP (1 << 7)
720 #define HWCAP_JAVA (1 << 8)
721 #define HWCAP_IWMMXT (1 << 9)
722 #define HWCAP_CRUNCH (1 << 10)
723 #define HWCAP_THUMBEE (1 << 11)
724 #define HWCAP_NEON (1 << 12)
725 #define HWCAP_VFPv3 (1 << 13)
726 #define HWCAP_VFPv3D16 (1 << 14)
727 #define HWCAP_TLS (1 << 15)
728 #define HWCAP_VFPv4 (1 << 16)
729 #define HWCAP_IDIVA (1 << 17)
730 #define HWCAP_IDIVT (1 << 18)
731 #define HWCAP_VFPD32 (1 << 19)
732 #define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT)
737 static unsigned GetARMCPUCaps(
void)
740 int fd = open(
"/proc/self/auxv", O_RDONLY);
754 num = read(fd, (
char*)&auxvec,
sizeof(auxvec));
756 if (num < 1 || (auxvec.a_type == 0 && auxvec.a_val == 0))
759 if (auxvec.a_type == AT_HWCAP)
774 #if defined(_M_ARM) || defined(_M_ARM64)
776 #include <sys/auxv.h>
780 BOOL IsProcessorFeaturePresent(DWORD ProcessorFeature)
784 const uint64_t features = android_getCpuFeatures();
786 switch (ProcessorFeature)
788 case PF_ARM_NEON_INSTRUCTIONS_AVAILABLE:
790 return features & ANDROID_CPU_ARM_FEATURE_NEON;
793 WLog_WARN(TAG,
"feature 0x%08" PRIx32
" check not implemented", ProcessorFeature);
797 #elif defined(_M_ARM) || defined(_M_ARM64)
799 const unsigned long caps = getauxval(AT_HWCAP);
801 switch (ProcessorFeature)
803 case PF_ARM_NEON_INSTRUCTIONS_AVAILABLE:
806 if (caps & HWCAP_NEON)
812 if (caps & HWCAP_THUMB)
815 case PF_ARM_VFP_32_REGISTERS_AVAILABLE:
816 if (caps & HWCAP_VFPD32)
819 case PF_ARM_DIVIDE_INSTRUCTION_AVAILABLE:
820 if ((caps & HWCAP_IDIVA) || (caps & HWCAP_IDIVT))
824 if (caps & HWCAP_VFPv3)
830 if (caps & HWCAP_JAVA)
836 if (caps & HWCAP_EDSP)
842 if (caps & HWCAP_EDSP)
848 if ((caps & HWCAP_IDIVT) || (caps & HWCAP_VFPv4))
854 if (caps & HWCAP_THUMBEE)
859 case PF_ARM_INTEL_WMMX:
860 if (caps & HWCAP_IWMMXT)
864 case PF_ARM_V8_INSTRUCTIONS_AVAILABLE:
865 case PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE:
866 case PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE:
867 case PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE:
868 case PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE:
869 case PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE:
870 case PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE:
872 WLog_WARN(TAG,
"feature 0x%08" PRIx32
" check not implemented", ProcessorFeature);
878 switch (ProcessorFeature)
880 case PF_ARM_NEON_INSTRUCTIONS_AVAILABLE:
886 case PF_ARM_V8_INSTRUCTIONS_AVAILABLE:
887 case PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE:
888 case PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE:
889 case PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE:
890 case PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE:
891 case PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE:
892 case PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE:
894 WLog_WARN(TAG,
"feature 0x%08" PRIx32
" check not implemented", ProcessorFeature);
901 #if defined(_M_IX86_AMD64)
907 cpuid(1, &a, &b, &c, &d);
909 switch (ProcessorFeature)
911 case PF_MMX_INSTRUCTIONS_AVAILABLE:
917 case PF_XMMI_INSTRUCTIONS_AVAILABLE:
923 case PF_XMMI64_INSTRUCTIONS_AVAILABLE:
929 case PF_3DNOW_INSTRUCTIONS_AVAILABLE:
935 case PF_SSE3_INSTRUCTIONS_AVAILABLE:
936 ret = __builtin_cpu_supports(
"sse3");
939 case PF_SSSE3_INSTRUCTIONS_AVAILABLE:
940 ret = __builtin_cpu_supports(
"ssse3");
942 case PF_SSE4_1_INSTRUCTIONS_AVAILABLE:
943 ret = __builtin_cpu_supports(
"sse4.1");
945 case PF_SSE4_2_INSTRUCTIONS_AVAILABLE:
946 ret = __builtin_cpu_supports(
"sse4.2");
948 case PF_AVX_INSTRUCTIONS_AVAILABLE:
949 ret = __builtin_cpu_supports(
"avx");
951 case PF_AVX2_INSTRUCTIONS_AVAILABLE:
952 ret = __builtin_cpu_supports(
"avx2");
954 case PF_AVX512F_INSTRUCTIONS_AVAILABLE:
955 ret = __builtin_cpu_supports(
"avx512f");
958 WLog_WARN(TAG,
"feature 0x%08" PRIx32
" check not implemented", ProcessorFeature);
967 switch (ProcessorFeature)
969 case PF_MMX_INSTRUCTIONS_AVAILABLE:
975 case PF_3DNOW_INSTRUCTIONS_AVAILABLE:
981 case PF_SSE3_INSTRUCTIONS_AVAILABLE:
997 DWORD GetTickCountPrecise(
void)
1002 QueryPerformanceFrequency(&freq);
1003 QueryPerformanceCounter(¤t);
1004 return (DWORD)(current.QuadPart * 1000LL / freq.QuadPart);
1006 return GetTickCount();
1010 BOOL IsProcessorFeaturePresentEx(DWORD ProcessorFeature)
1013 #if defined(_M_ARM) || defined(_M_ARM64)
1016 caps = GetARMCPUCaps();
1018 switch (ProcessorFeature)
1020 case PF_EX_ARM_VFP1:
1021 if (caps & HWCAP_VFP)
1026 case PF_EX_ARM_VFP3D16:
1027 if (caps & HWCAP_VFPv3D16)
1032 case PF_EX_ARM_VFP4:
1033 if (caps & HWCAP_VFPv4)
1038 case PF_EX_ARM_IDIVA:
1039 if (caps & HWCAP_IDIVA)
1044 case PF_EX_ARM_IDIVT:
1045 if (caps & HWCAP_IDIVT)
1052 #elif defined(_M_IX86_AMD64)
1057 cpuid(1, &a, &b, &c, &d);
1059 switch (ProcessorFeature)
1067 cpuid(0x80000001, &a81, &b81, &c81, &d81);
1069 if (c81 & C81_BIT_LZCNT)
1074 case PF_EX_3DNOW_PREFETCH:
1081 if (c & C_BIT_SSSE3)
1087 if (c & C_BIT_SSE41)
1093 if (c & C_BIT_SSE42)
1097 #if defined(__GNUC__) || defined(_MSC_VER)
1104 case PF_EX_AVX_PCLMULQDQ:
1107 if (!(c & C_BIT_AVX))
1111 if (!(c & C_BIT_XGETBV))
1119 if ((e & E_BITS_AVX) == E_BITS_AVX)
1121 switch (ProcessorFeature)
1129 cpuid(7, &a, &b, &c, &d);
1130 switch (ProcessorFeature)
1138 if (b & B_BIT_AVX512F)
1159 case PF_EX_AVX_PCLMULQDQ:
1160 if (c & C_BIT_PCLMULQDQ)
1175 #elif defined(_M_E2K)
1177 switch (ProcessorFeature)