I'm looking at some library code that performs the following. The CpuId
function operates as expected. It loads EAX
(function), ECX
(subfunction) and then calls 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();
Then, this is what the code does in 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;
}
Calling CPUID
and testing bit 26 of EDX
is correct per Intel® 64 and IA-32 Architectures Software Developer Manual, Volume 2, Figure 3-8, page 3-192. So I'm not sure about the TrySSE2
part...
I have looked at other similar questions, like Determine processor support for SSE2?. None of them say testing EDX:26
is unreliable.
Why would the code call TrySSE2
rather than using CPUID/EDX:26
? Is the test unreliable on some non-Intel processors?
When the SSE instructions were added, they introduced new registers which need to be saved/restored during context switches... since OSes at the time didn't have the code to do this, the SSE instructions were disabled by default.
Once OSes were updated to support saving/restoring these new registers, the OS would then enable the SSE instructions. Nowadays all OSes have SSE support, but I suspect this code is checking that:
See here for a bit more info: http://wiki.osdev.org/SSE#Checking_for_SSE