Skip to content

Commit 2423cdd

Browse files
committed
Merge pull request opencv#10852 from alalek:fix_cpuid
2 parents 7474ad8 + eb54e5c commit 2423cdd

File tree

1 file changed

+43
-106
lines changed

1 file changed

+43
-106
lines changed

modules/core/src/system.cpp

Lines changed: 43 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -105,45 +105,6 @@ Mutex* __initialization_mutex_initializer = &getInitializationMutex();
105105
#undef max
106106
#undef abs
107107
#include <tchar.h>
108-
#if defined _MSC_VER
109-
#if _MSC_VER >= 1400
110-
#include <intrin.h>
111-
#elif defined _M_IX86
112-
static void __cpuid(int* cpuid_data, int)
113-
{
114-
__asm
115-
{
116-
push ebx
117-
push edi
118-
mov edi, cpuid_data
119-
mov eax, 1
120-
cpuid
121-
mov [edi], eax
122-
mov [edi + 4], ebx
123-
mov [edi + 8], ecx
124-
mov [edi + 12], edx
125-
pop edi
126-
pop ebx
127-
}
128-
}
129-
static void __cpuidex(int* cpuid_data, int, int)
130-
{
131-
__asm
132-
{
133-
push edi
134-
mov edi, cpuid_data
135-
mov eax, 7
136-
mov ecx, 0
137-
cpuid
138-
mov [edi], eax
139-
mov [edi + 4], ebx
140-
mov [edi + 8], ecx
141-
mov [edi + 12], edx
142-
pop edi
143-
}
144-
}
145-
#endif
146-
#endif
147108

148109
#ifdef WINRT
149110
#include <wrl/client.h>
@@ -228,6 +189,44 @@ std::wstring GetTempFileNameWinRT(std::wstring prefix)
228189
# include <android/log.h>
229190
#endif
230191

192+
#ifdef DECLARE_CV_CPUID_X86
193+
DECLARE_CV_CPUID_X86
194+
#endif
195+
#ifndef CV_CPUID_X86
196+
#if defined _MSC_VER && (defined _M_IX86 || defined _M_X64)
197+
#if _MSC_VER >= 1400 // MSVS 2005
198+
#include <intrin.h> // __cpuidex()
199+
#define CV_CPUID_X86 __cpuidex
200+
#else
201+
#error "Required MSVS 2005+"
202+
#endif
203+
#elif defined __GNUC__ && (defined __i386__ || defined __x86_64__)
204+
static void cv_cpuid(int* cpuid_data, int reg_eax, int reg_ecx)
205+
{
206+
int __eax = reg_eax, __ebx = 0, __ecx = reg_ecx, __edx = 0;
207+
// tested with available compilers (-fPIC -O2 -m32/-m64): https://godbolt.org/
208+
#if !defined(__PIC__) \
209+
|| defined(__x86_64__) || __GNUC__ >= 5 \
210+
|| defined(__clang__) || defined(__INTEL_COMPILER)
211+
__asm__("cpuid\n\t"
212+
: "+a" (__eax), "=b" (__ebx), "+c" (__ecx), "=d" (__edx)
213+
);
214+
#elif defined(__i386__) // ebx may be reserved as the PIC register
215+
__asm__("xchg{l}\t{%%}ebx, %1\n\t"
216+
"cpuid\n\t"
217+
"xchg{l}\t{%%}ebx, %1\n\t"
218+
: "+a" (__eax), "=&r" (__ebx), "+c" (__ecx), "=d" (__edx)
219+
);
220+
#else
221+
#error "Configuration error"
222+
#endif
223+
cpuid_data[0] = __eax; cpuid_data[1] = __ebx; cpuid_data[2] = __ecx; cpuid_data[3] = __edx;
224+
}
225+
#define CV_CPUID_X86 cv_cpuid
226+
#endif
227+
#endif
228+
229+
231230
namespace cv
232231
{
233232

@@ -325,38 +324,12 @@ struct HWFeatures
325324

326325
initializeNames();
327326

327+
#ifdef CV_CPUID_X86
328328
int cpuid_data[4] = { 0, 0, 0, 0 };
329329
int cpuid_data_ex[4] = { 0, 0, 0, 0 };
330330

331-
#if defined _MSC_VER && (defined _M_IX86 || defined _M_X64)
332-
#define OPENCV_HAVE_X86_CPUID 1
333-
__cpuid(cpuid_data, 1);
334-
#elif defined __GNUC__ && (defined __i386__ || defined __x86_64__)
335-
#define OPENCV_HAVE_X86_CPUID 1
336-
#ifdef __x86_64__
337-
asm __volatile__
338-
(
339-
"movl $1, %%eax\n\t"
340-
"cpuid\n\t"
341-
:[eax]"=a"(cpuid_data[0]),[ebx]"=b"(cpuid_data[1]),[ecx]"=c"(cpuid_data[2]),[edx]"=d"(cpuid_data[3])
342-
:
343-
: "cc"
344-
);
345-
#else
346-
asm volatile
347-
(
348-
"pushl %%ebx\n\t"
349-
"movl $1,%%eax\n\t"
350-
"cpuid\n\t"
351-
"popl %%ebx\n\t"
352-
: "=a"(cpuid_data[0]), "=c"(cpuid_data[2]), "=d"(cpuid_data[3])
353-
:
354-
: "cc"
355-
);
356-
#endif
357-
#endif
331+
CV_CPUID_X86(cpuid_data, 1, 0/*unused*/);
358332

359-
#ifdef OPENCV_HAVE_X86_CPUID
360333
int x86_family = (cpuid_data[0] >> 8) & 15;
361334
if( x86_family >= 6 )
362335
{
@@ -374,38 +347,8 @@ struct HWFeatures
374347

375348
// make the second call to the cpuid command in order to get
376349
// information about extended features like AVX2
377-
#if defined _MSC_VER && (defined _M_IX86 || defined _M_X64)
378-
#define OPENCV_HAVE_X86_CPUID_EX 1
379-
__cpuidex(cpuid_data_ex, 7, 0);
380-
#elif defined __GNUC__ && (defined __i386__ || defined __x86_64__)
381-
#define OPENCV_HAVE_X86_CPUID_EX 1
382-
#ifdef __x86_64__
383-
asm __volatile__
384-
(
385-
"movl $7, %%eax\n\t"
386-
"movl $0, %%ecx\n\t"
387-
"cpuid\n\t"
388-
:[eax]"=a"(cpuid_data_ex[0]),[ebx]"=b"(cpuid_data_ex[1]),[ecx]"=c"(cpuid_data_ex[2]),[edx]"=d"(cpuid_data_ex[3])
389-
:
390-
: "cc"
391-
);
392-
#else
393-
asm volatile
394-
(
395-
"pushl %%ebx\n\t"
396-
"movl $7,%%eax\n\t"
397-
"movl $0,%%ecx\n\t"
398-
"cpuid\n\t"
399-
"movl %%ebx, %0\n\t"
400-
"popl %%ebx\n\t"
401-
: "=r"(cpuid_data_ex[1]), "=c"(cpuid_data_ex[2])
402-
:
403-
: "cc"
404-
);
405-
#endif
406-
#endif
350+
CV_CPUID_X86(cpuid_data_ex, 7, 0);
407351

408-
#ifdef OPENCV_HAVE_X86_CPUID_EX
409352
have[CV_CPU_AVX2] = (cpuid_data_ex[1] & (1<<5)) != 0;
410353

411354
have[CV_CPU_AVX_512F] = (cpuid_data_ex[1] & (1<<16)) != 0;
@@ -417,9 +360,6 @@ struct HWFeatures
417360
have[CV_CPU_AVX_512BW] = (cpuid_data_ex[1] & (1<<30)) != 0;
418361
have[CV_CPU_AVX_512VL] = (cpuid_data_ex[1] & (1<<31)) != 0;
419362
have[CV_CPU_AVX_512VBMI] = (cpuid_data_ex[2] & (1<<1)) != 0;
420-
#else
421-
CV_UNUSED(cpuid_data_ex);
422-
#endif
423363

424364
bool have_AVX_OS_support = true;
425365
bool have_AVX512_OS_support = true;
@@ -431,7 +371,7 @@ struct HWFeatures
431371
#ifdef _XCR_XFEATURE_ENABLED_MASK // requires immintrin.h
432372
xcr0 = (int)_xgetbv(_XCR_XFEATURE_ENABLED_MASK);
433373
#elif defined __GNUC__ && (defined __i386__ || defined __x86_64__)
434-
__asm__ ("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx" );
374+
__asm__ ("xgetbv\n\t" : "=a" (xcr0) : "c" (0) : "%edx" );
435375
#endif
436376
if ((xcr0 & 0x6) != 0x6)
437377
have_AVX_OS_support = false; // YMM registers
@@ -464,10 +404,7 @@ struct HWFeatures
464404
have[CV_CPU_AVX512_SKX] = have[CV_CPU_AVX_512F] & have[CV_CPU_AVX_512CD] & have[CV_CPU_AVX_512BW] & have[CV_CPU_AVX_512DQ] & have[CV_CPU_AVX_512VL];
465405
}
466406
}
467-
#else
468-
CV_UNUSED(cpuid_data);
469-
CV_UNUSED(cpuid_data_ex);
470-
#endif // OPENCV_HAVE_X86_CPUID
407+
#endif // CV_CPUID_X86
471408

472409
#if defined __ANDROID__ || defined __linux__
473410
#ifdef __aarch64__

0 commit comments

Comments
 (0)