Add subfunc to CpuId for AVX and above

pull/461/head
Jeffrey Walton 2017-08-11 22:56:01 -04:00
parent f02503d08f
commit a84f568ee2
No known key found for this signature in database
GPG Key ID: B36AB348921B1838
1 changed files with 33 additions and 22 deletions

55
cpu.cpp
View File

@ -28,11 +28,22 @@ extern "C" {
#ifdef CRYPTOPP_CPUID_AVAILABLE #ifdef CRYPTOPP_CPUID_AVAILABLE
#if _MSC_VER >= 1400 && CRYPTOPP_BOOL_X64 #if _MSC_VER >= 1500
bool CpuId(word32 input, word32 output[4]) static inline bool CpuId(word32 func, word32 subfunc, word32 output[4])
{ {
__cpuid((int *)output, input); __cpuidex((int *)output, func, subfunc);
return true;
}
#elif _MSC_VER >= 1400 && CRYPTOPP_BOOL_X64
static inline bool CpuId(word32 func, word32 subfunc, word32 output[4])
{
if (subfunc != 0)
return false;
__cpuid((int *)output, func);
return true; return true;
} }
@ -55,15 +66,15 @@ extern "C"
} }
#endif #endif
bool CpuId(word32 input, word32 output[4]) static inline bool CpuId(word32 func, word32 subfunc, word32 output[4])
{ {
#if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) #if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY)
__try __try
{ {
__asm __asm
{ {
mov eax, input mov eax, func
mov ecx, 0 mov ecx, subfunc
cpuid cpuid
mov edi, output mov edi, output
mov [edi], eax mov [edi], eax
@ -112,7 +123,7 @@ bool CpuId(word32 input, word32 output[4])
"push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx" "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
# endif # endif
: "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3]) : "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3])
: "a" (input), "c" (0) : "a" (func), "c" (subfunc)
: "cc" : "cc"
); );
} }
@ -221,9 +232,9 @@ void DetectX86Features()
{ {
// Coverity finding CID 171239... // Coverity finding CID 171239...
word32 cpuid0[4]={0}, cpuid1[4]={0}, cpuid2[4]={0}; word32 cpuid0[4]={0}, cpuid1[4]={0}, cpuid2[4]={0};
if (!CpuId(0, cpuid0)) if (!CpuId(0, 0, cpuid0))
return; return;
if (!CpuId(1, cpuid1)) if (!CpuId(1, 0, cpuid1))
return; return;
if ((cpuid1[3] & (1 << 26)) != 0) if ((cpuid1[3] & (1 << 26)) != 0)
@ -244,9 +255,9 @@ void DetectX86Features()
g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1); g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1);
g_hasRDRAND = !!(cpuid1[2] /*ECX*/ & RDRAND_FLAG); g_hasRDRAND = !!(cpuid1[2] /*ECX*/ & RDRAND_FLAG);
if (cpuid0[0] /*EAX*/ >= 7) if (cpuid1[0] /*EAX*/ >= 7)
{ {
if (CpuId(7, cpuid2)) if (CpuId(7, 0, cpuid2))
{ {
g_hasRDSEED = !!(cpuid2[1] /*EBX*/ & RDSEED_FLAG); g_hasRDSEED = !!(cpuid2[1] /*EBX*/ & RDSEED_FLAG);
g_hasSHA = !!(cpuid2[1] /*EBX*/ & SHA_FLAG); g_hasSHA = !!(cpuid2[1] /*EBX*/ & SHA_FLAG);
@ -259,13 +270,13 @@ void DetectX86Features()
enum { RDSEED_FLAG = (1 << 18) }; enum { RDSEED_FLAG = (1 << 18) };
enum { SHA_FLAG = (1 << 29) }; enum { SHA_FLAG = (1 << 29) };
CpuId(0x80000005, cpuid2); CpuId(0x80000005, 0, cpuid2);
g_cacheLineSize = GETBYTE(cpuid2[2], 0); g_cacheLineSize = GETBYTE(cpuid2[2], 0);
g_hasRDRAND = !!(cpuid1[2] /*ECX*/ & RDRAND_FLAG); g_hasRDRAND = !!(cpuid1[2] /*ECX*/ & RDRAND_FLAG);
if (cpuid0[0] /*EAX*/ >= 7) if (cpuid1[0] /*EAX*/ >= 7)
{ {
if (CpuId(7, cpuid2)) if (CpuId(7, 0, cpuid2))
{ {
g_hasRDSEED = !!(cpuid2[1] /*EBX*/ & RDSEED_FLAG); g_hasRDSEED = !!(cpuid2[1] /*EBX*/ & RDSEED_FLAG);
g_hasSHA = !!(cpuid2[1] /*EBX*/ & SHA_FLAG); g_hasSHA = !!(cpuid2[1] /*EBX*/ & SHA_FLAG);
@ -280,16 +291,16 @@ void DetectX86Features()
enum { PHE_FLAGS = (0x3 << 10) }; enum { PHE_FLAGS = (0x3 << 10) };
enum { PMM_FLAGS = (0x3 << 12) }; enum { PMM_FLAGS = (0x3 << 12) };
CpuId(0xC0000000, cpuid0); CpuId(0xC0000000, 0, cpuid2);
if (cpuid0[0] >= 0xC0000001) if (cpuid2[0] >= 0xC0000001)
{ {
// Extended features available // Extended features available
CpuId(0xC0000001, cpuid0); CpuId(0xC0000001, 0, cpuid2);
g_hasPadlockRNG = !!(cpuid0[3] /*EDX*/ & RNG_FLAGS); g_hasPadlockRNG = !!(cpuid2[3] /*EDX*/ & RNG_FLAGS);
g_hasPadlockACE = !!(cpuid0[3] /*EDX*/ & ACE_FLAGS); g_hasPadlockACE = !!(cpuid2[3] /*EDX*/ & ACE_FLAGS);
g_hasPadlockACE2 = !!(cpuid0[3] /*EDX*/ & ACE2_FLAGS); g_hasPadlockACE2 = !!(cpuid2[3] /*EDX*/ & ACE2_FLAGS);
g_hasPadlockPHE = !!(cpuid0[3] /*EDX*/ & PHE_FLAGS); g_hasPadlockPHE = !!(cpuid2[3] /*EDX*/ & PHE_FLAGS);
g_hasPadlockPMM = !!(cpuid0[3] /*EDX*/ & PMM_FLAGS); g_hasPadlockPMM = !!(cpuid2[3] /*EDX*/ & PMM_FLAGS);
} }
} }