检查我的平台上是否存在命令 AVX、SSE (SSE1-SSE4.2)、FPU

Check exist on my platform commands AVX, SSE (SSE1-SSE4.2), FPU

我有一个任务:检查我的平台上是否存在命令 AVX、SSE (SSE1-SSE4.2)、FPU。 我的汇编代码不工作,我不明白为什么。 我认为是不正确的描述输出修饰符。

    unsigned int AVX;
unsigned int SSE1;
unsigned int SSE2;
unsigned int SSE3;
unsigned int SSSE3;
unsigned int SSE41;
unsigned int SSE42;
unsigned int FPU;
__asm__(
    "cpuid\n\t"
    "movl %%edx, %[AVX]\n\t"
    "and $(1<<28), %[AVX]\n\t"
    "movl %%edx, %[SSE1]\n\t"
    "and $(1<<25), %[SSE1]\n\t"
    "movl %%edx, %[SSE2]\n\t"
    "and $(1<<26), %[SSE2]\n\t"
    "movl %%ecx, %[SSE3]\n\t"
    "and $(1<<9), %[SSE3]\n\t"
    "movl %%ecx, %[SSSE3]\n\t"
    "and $(1<<9), %[SSSE3]\n\t"
    "movl %%edx, %[SSE41]\n\t"
    "and $(1<<19), %[SSE41]\n\t"
    "movl %%ecx, %[SSE42]\n\t"
    "and $(1<<20), %[SSE42]\n\t"
    "movl %%edx, %[FPU]\n\t"
    "and $(1<<0), %[FPU]\n\t"
    : [AVX] "=&r"(AVX), [SSE1]"=&r"(SSE1), 
      [SSE2]"=&r"(SSE2), [SSE3]"=&r"(SSE3), 
      [SSSE3]"=&r"(SSSE3), [SSE41]"=&r"(SSE41),
      [SSE42]"=&r"(SSE42), [FPU]"=&r"(FPU)
    : "a"(1)
    : "cc"
);
cout << "AVX:" << (bool)AVX << endl;
cout << "SSE1:" << (bool)SSE1 << endl;
cout << "SSE2:" << (bool)SSE2 << endl;
cout << "SSE3:" << (bool)SSE3 << endl;
cout << "SSSE3:" << (bool)SSSE3 << endl;
cout << "SSE41:" << (bool)SSE41 << endl;
cout << "SSE42:" << (bool)SSE42 << endl;
cout << "FPU:" << (bool)FPU << endl;

错误:'asm'操作数具有不可能的约束

在32位模式下编程时,通用寄存器只有六七个,所以编译器无法将八个输出操作数和一个输入操作数分配给寄存器。您还忘记声明正确的 clobbers(cpuid clobbers eaxebxecxedx),如果不更正,将在运行时导致意外行为.

最好不要内联汇编来做这种事情,例如使用某种库或 gcc 的内置函数:

int AVX, SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42;

__builtin_cpu_init();
SSE1 = __builtin_cpu_supports("sse");
SSE2 = __builtin_cpu_supports("sse2");
SSE3 = __builtin_cpu_supports("sse3");
SSSE3 = __builtin_cpu_supports("ssse3");
SSE41 = __builtin_cpu_supports("sse4.1");
SSE42 = __builtin_cpu_supports("sse4.2");
AVX = __builtin_cpu_supports("avx");

同时考虑使用 Intel 内部函数 _may_i_use_cpu_feature and the <cpuid.h> interface

请注意,检查这些位并不能告诉您操作系统是否实际启用了 CPU 功能,因此尝试使用这些功能的代码可能仍会在运行时崩溃。

如果必须使用内联汇编,请尽量减少内联汇编的工作量。

int eax = 1, ecx, edx;
int AVX, FPU, SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42;

asm ("cpuid" : "+a"(eax), "=c"(ecx), "=d"(edx) :: "ebx");
FPU   = edx & 1 <<  0;
AVX   = ecx & 1 << 28;
SSE1  = edx & 1 << 25;
SSE2  = edx & 1 << 26;
SSE3  = ecx & 1 <<  0;
SSSE3 = ecx & 1 <<  9;
SSE41 = ecx & 1 << 19;
SSE42 = ecx & 1 << 20;