使用 CPUID 测试 SSE2 与尝试 SSE2 指令和 SIGILL?

Test for SSE2 using CPUID versus trying SSE2 instruction and SIGILL?

我正在查看一些执行以下操作的库代码。 CpuId 函数按预期运行。它加载 EAX(函数),ECX(子函数),然后调用 CPUID.

struct CPUIDinfo
{
    word32 EAX;
    word32 EBX;
    word32 ECX;
    word32 EDX;
};
...

CPUIDinfo info;
CpuId(1 /*EAX=1*/, 0 /*ECX=0*, info);

if ((info.EDX & (1 << 26)) != 0)
    s_hasSSE2 = TrySSE2();

然后,这就是代码在 TrySSE2 中的作用:

bool TrySSE2()
{
    /* SIG handlers in place */

    // Sets XMM0 to 0
    por xmm0, xmm0;

    #if ... Microsoft and instrinsics available ...
      // Exercises MOVD instruction
      word32 x = _mm_cvtsi128_si32(xmm0);
      return x == 0;
    #endif

    return true;
}

根据 Intel® 64 and IA-32 Architectures Software Developer Manual,第 2 卷,图 3-8,第 3-192 页,调用 CPUID 并测试 EDX 的第 26 位是正确的。所以我不确定 TrySSE2 部分...

我看过其他类似的问题,比如 Determine processor support for SSE2?。 None 他们说测试 EDX:26 不可靠。

为什么代码会调用 TrySSE2 而不是使用 CPUID/EDX:26?测试是否在某些非英特尔处理器上不可靠?

添加 SSE 指令时,他们引入了新的寄存器,在上下文切换期间需要 saved/restored... 因为当时 OSes 没有代码来执行此操作, SSE 指令默认禁用。

更新 OSes 以支持 saving/restoring 这些新寄存器后,OS 将启用 SSE 指令。现在所有 OSes 都支持 SSE,但我怀疑这段代码正在检查:

  • CPU 支持 SSE2
  • OS 已启用 SSE2

查看此处了解更多信息:http://wiki.osdev.org/SSE#Checking_for_SSE