CPU detection C code

Programming Topics (Computer Chess) and technical aspects as test techniques, book building, program tuning etc

Moderator: Andres Valverde

CPU detection C code

Postby Jim Ablett » 18 Oct 2004, 13:33

Here's some handy cpu detection C code, I found whilst trawling the web - you may find it useful >

///////////////////////////////////////////////////////////////////////////////
////////// Source code to detect which CPU is in the user's computer.
//////////Update 14/7/04- fix for SSE and Windows XP
///////////////////////////////////////////////////////////////////////////////

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define FALSE 0
#define TRUE 1

int AvailCPUID (void)
{
/* Tests for availability of CPUID by flipping ID bit eflags */
int f=FALSE;
__asm
{
pushfd
pop eax
mov ebx,eax
xor eax,0x00200000
push eax
popfd
pushfd
pop eax
push ebx
popfd
xor eax,ebx
mov f,eax
}

return f;
}

int FirstCPUID (char *s)
{
int Level;
// Find processor manufacturer and number of supported CPUID modes
__asm
{
xor eax,eax
cpuid
mov Level,eax
mov esi,s
mov dword ptr [esi],ebx
mov dword ptr 4[esi],edx
mov dword ptr 8[esi],ecx
}
s [12] = 0;
return Level;
}

int FirstAMDCPUID (void)
{
int Level;
// Finds number of supported AMD extended CPUID modes
__asm
{
mov eax,80000000H
cpuid
mov Level,eax
}
return Level;
}

unsigned int VersionCPUID (void)
{
unsigned int Features;
// Finds features of CPU
__asm
{
mov eax,1
cpuid
mov Features,edx
}
return Features;
}

int FamilyCPUID (void)
{
unsigned int Family;
// Finds family of CPU
__asm
{
mov eax,1
cpuid
mov Family,eax
}
return Family;
}

unsigned int AMDVersionCPUID (void)
{
unsigned int Features;
// Finds AMD extended features of CPU
__asm
{
mov eax,80000001H
cpuid
mov Features,edx
}
return Features;
}

int isPentium (void)
{
char Brand [64];
unsigned int Features;
// Returns TRUE if processor is a Pentium or compatible.
if (!AvailCPUID ()) return FALSE; // no CPUID
if (FamilyCPUID () < 5) return FALSE; // must be 486
Features = VersionCPUID ();
if (!(Features & 0x1)) return FALSE; // no float
return TRUE;
}

int isPentiumMMX (void)
{
char Brand [64];
unsigned int Features;
// Returns TRUE if processor is a Pentium with MMX or compatible.
if (!AvailCPUID ()) return FALSE;
if (FamilyCPUID () < 5) return FALSE;
Features = VersionCPUID ();
if (!(Features & 0x1)) return FALSE; // no float
if (!(Features & 0x800000)) return FALSE; // no MMX
return TRUE;
}

int isPentiumPro (void)
{
char Brand [64];
unsigned int Features;
// Returns TRUE if processor is a Pentium Pro or compatible.
if (!AvailCPUID ()) return FALSE;
if (FamilyCPUID () < 6) return FALSE;
Features = VersionCPUID ();
if (!(Features & 0x1)) return FALSE; // no float
if (!(Features & 0x8000)) return FALSE; // no CMOV/FCMOV/FCOMI
return TRUE;
}

int isPentiumII (void)
{
char Brand [64];
unsigned int Features;
// Returns TRUE if processor is a Pentium II or compatible.
if (!AvailCPUID ()) return FALSE;
if (FamilyCPUID () < 6) return FALSE;
Features = VersionCPUID ();
if (!(Features & 0x1)) return FALSE; // no float
if (!(Features & 0x8000)) return FALSE; // no CMOV/FCMOV/FCOMI
if (!(Features & 0x800000)) return FALSE; // no MMX
return TRUE;
}

int isPentiumIII (void)
{
char Brand [64];
unsigned int Features;
// Returns TRUE if processor is a Pentium III or compatible.
// Returns FALSE if Pentium III with no operating system support
if (!AvailCPUID ()) return FALSE;
if (FamilyCPUID () < 6) return FALSE;
Features = VersionCPUID ();
if (!(Features & 0x1)) return FALSE; // no float
if (!(Features & 0x8000)) return FALSE; // no CMOV/FCMOV/FCOMI
if (!(Features & 0x800000)) return FALSE; // no MMX
if (!(Features & 0x2000000)) return FALSE; // no Streaming SIMD
return TRUE;
}

int isAMDK6 (void)
{
char Brand [64];
unsigned int Features;
// Returns TRUE if processor is an AMD K6 with MMX or compatible.
// Returns FALSE if processor is a Pentium MMX, even though this
// is a compatible processor. Use isPentiumMMX for that.
if (!AvailCPUID ()) return FALSE;
if (FamilyCPUID () < 5) return FALSE; // not Pentium class or above
if (FirstCPUID (Brand) < 1) return FALSE;
if (FirstAMDCPUID () < 0x80000001) return FALSE;
Features = AMDVersionCPUID ();
if (!(Features & 0x1)) return FALSE; // no float
if (!(Features & 0x800000)) return FALSE; // no MMX
return TRUE;
}

int isAMDK62 (void)
{
char Brand [64];
unsigned int Features;
// Returns TRUE if processor is an AMD K6 with MMX and 3DNow! or compatible.
if (!AvailCPUID ()) return FALSE;
if (FamilyCPUID () < 5) return FALSE; // not Pentium class or above
if (FirstCPUID (Brand) < 1) return FALSE;
if (FirstAMDCPUID () < 0x80000001) return FALSE;
Features = AMDVersionCPUID ();
if (!(Features & 0x1)) return FALSE; // no float
if (!(Features & 0x800000)) return FALSE; // no MMX
if (!(Features & 0x80000000)) return FALSE; // no 3DNow!
return TRUE;
}

int isAthlon (void)
{
char Brand [64];
unsigned int Features;
// Returns TRUE if processor is an AMD Athlon with MMX and Advanced 3DNow! or compatible.
if (!AvailCPUID ()) return FALSE;
if (FamilyCPUID () < 6) return FALSE; // not Pentium Pro class or above
if (FirstCPUID (Brand) < 1) return FALSE;
if (FirstAMDCPUID () < 0x80000001) return FALSE;
Features = AMDVersionCPUID ();
if (!(Features & 0x1)) return FALSE; // no float
if (!(Features & 0x8000)) return FALSE; // no CMOV/FCMOV/FCOMI
if (!(Features & 0x800000)) return FALSE; // no MMX
if (!(Features & 0x400000)) return FALSE; // no K7 MMX
if (!(Features & 0x80000000)) return FALSE; // no 3DNow!
if (!(Features & 0x40000000)) return FALSE; // no Advanced 3DNow!
return TRUE;
}

void main (void)
{
int Avail, Level;
unsigned int Features, AMDLevel, AMDFeatures;
char Brand [64];

if (AvailCPUID ())
{
printf ("CPUID available\n");
Level = FirstCPUID (Brand);
printf ("CPUID brand: %s, max eax value: %d\n", Brand, Level);
if (Level >= 1)
{
printf ("Family = %d\n", (FamilyCPUID () >> 8) & 0xF);
Features = VersionCPUID ();
if (Features & 1) printf ("Floating-point\n");
if (Features & 0x8000) printf ("CMOV / FCMOV / FCOMI supported\n");
if (Features & 0x800000) printf ("MMX supported\n");
if (Features & 0x2000000)
{
printf ("Streaming SIMD Extensions supported by processor\n");
}
AMDLevel = FirstAMDCPUID ();
if (AMDLevel >= 0x80000001)
{
AMDFeatures = AMDVersionCPUID ();
if (AMDFeatures & 0x400000) printf ("AMD K7 MMX Extensions\n");
if (AMDFeatures & 0x40000000) printf ("AMD K7 3DNow! Extensions\n");
if (AMDFeatures & 0x80000000) printf ("AMD 3DNow! Extensions\n");
}
}
}
else
printf ("CPUID not available - must be 486 or less\n");
if (isPentium ()) printf ("isPentium\n");
if (isPentiumMMX ()) printf ("isPentiumMMX\n");
if (isPentiumPro ()) printf ("isPentiumPro\n");
if (isPentiumII ()) printf ("isPentiumII\n");
if (isPentiumIII ()) printf ("isPentiumIII\n");
if (isAMDK6 ()) printf ("isAMDK6\n");
if (isAMDK62 ()) printf ("isAMDK62\n");
if (isAthlon ()) printf ("isAthlon\n");
}

//////////////////// code end ///////////////////////////////////////////////
Jim Ablett
 
Posts: 721
Joined: 27 Sep 2004, 10:39
Location: Essex, England

Re: CPU detection C code

Postby Volker Pittlik » 18 Oct 2004, 14:20

Jim Ablett wrote:Here's some handy cpu detection C code, I found whilst trawling the web - you may find it useful >

Code: Select all
///////////////////////////////////////////////////////////////////////////////
////////// Source code to detect which CPU is in the user's computer.
//////////Update 14/7/04- fix for SSE and Windows XP
///////////////////////////////////////////////////////////////////////////////

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define FALSE 0
#define TRUE 1

int AvailCPUID (void)
    {
    /* Tests for availability of CPUID by flipping ID bit eflags */
    int f=FALSE;
    __asm
   {
   pushfd
   pop eax
   mov ebx,eax
   xor eax,0x00200000
   push eax
   popfd
   pushfd
   pop eax
   push ebx
   popfd
   xor eax,ebx
   mov f,eax
   }

    return f;
    }

int FirstCPUID (char *s)
    {
    int Level;
    // Find processor manufacturer and number of supported CPUID modes
    __asm
   {
   xor eax,eax
   cpuid
   mov Level,eax
   mov esi,s
   mov dword ptr [esi],ebx
   mov dword ptr 4[esi],edx
   mov dword ptr 8[esi],ecx
   }
    s [12] = 0;
    return Level;
    }

int FirstAMDCPUID (void)
    {
    int Level;
    // Finds number of supported AMD extended CPUID modes
    __asm
   {
   mov eax,80000000H
   cpuid
   mov Level,eax
   }
    return Level;
    }

unsigned int VersionCPUID (void)
    {
    unsigned int Features;
    // Finds features of CPU
    __asm
   {
   mov eax,1
   cpuid
   mov Features,edx
   }
    return Features;
    }

int FamilyCPUID (void)
    {
    unsigned int Family;
    // Finds family of CPU
    __asm
   {
   mov eax,1
   cpuid
   mov Family,eax
   }
    return Family;
    }

unsigned int AMDVersionCPUID (void)
    {
    unsigned int Features;
    // Finds AMD extended features of CPU
    __asm
   {
   mov eax,80000001H
   cpuid
   mov Features,edx
   }
    return Features;
    }

int isPentium (void)
    {
    char Brand [64];
    unsigned int Features;
    // Returns TRUE if processor is a Pentium or compatible.
    if (!AvailCPUID ()) return FALSE;       // no CPUID
    if (FamilyCPUID () < 5) return FALSE;   // must be 486
    Features = VersionCPUID ();
    if (!(Features & 0x1)) return FALSE;    // no float
    return TRUE;
    }

int isPentiumMMX (void)
    {
    char Brand [64];
    unsigned int Features;
    // Returns TRUE if processor is a Pentium with MMX or compatible.
    if (!AvailCPUID ()) return FALSE;
    if (FamilyCPUID () < 5) return FALSE;
    Features = VersionCPUID ();
    if (!(Features & 0x1)) return FALSE;    // no float
    if (!(Features & 0x800000)) return FALSE; // no MMX
    return TRUE;
    }

int isPentiumPro (void)
    {
    char Brand [64];
    unsigned int Features;
    // Returns TRUE if processor is a Pentium Pro or compatible.
    if (!AvailCPUID ()) return FALSE;
    if (FamilyCPUID () < 6) return FALSE;
    Features = VersionCPUID ();
    if (!(Features & 0x1)) return FALSE;    // no float
    if (!(Features & 0x8000)) return FALSE; // no CMOV/FCMOV/FCOMI
    return TRUE;
    }

int isPentiumII (void)
    {
    char Brand [64];
    unsigned int Features;
    // Returns TRUE if processor is a Pentium II or compatible.
    if (!AvailCPUID ()) return FALSE;
    if (FamilyCPUID () < 6) return FALSE;
    Features = VersionCPUID ();
    if (!(Features & 0x1)) return FALSE;    // no float
    if (!(Features & 0x8000)) return FALSE; // no CMOV/FCMOV/FCOMI
    if (!(Features & 0x800000)) return FALSE; // no MMX
    return TRUE;
    }

int isPentiumIII (void)
    {
    char Brand [64];
    unsigned int Features;
    // Returns TRUE if processor is a Pentium III or compatible.
    // Returns FALSE if Pentium III with no operating system support
    if (!AvailCPUID ()) return FALSE;
    if (FamilyCPUID () < 6) return FALSE;
    Features = VersionCPUID ();
    if (!(Features & 0x1)) return FALSE;    // no float
    if (!(Features & 0x8000)) return FALSE; // no CMOV/FCMOV/FCOMI
    if (!(Features & 0x800000)) return FALSE; // no MMX
    if (!(Features & 0x2000000)) return FALSE; // no Streaming SIMD
    return TRUE;
    }

int isAMDK6 (void)
    {
    char Brand [64];
    unsigned int Features;
    // Returns TRUE if processor is an AMD K6 with MMX or compatible.
    // Returns FALSE if processor is a Pentium MMX, even though this
    // is a compatible processor. Use isPentiumMMX for that.
    if (!AvailCPUID ()) return FALSE;
    if (FamilyCPUID () < 5) return FALSE;    // not Pentium class or above
    if (FirstCPUID (Brand) < 1) return FALSE;
    if (FirstAMDCPUID () < 0x80000001) return FALSE;
    Features = AMDVersionCPUID ();
    if (!(Features & 0x1)) return FALSE;    // no float
    if (!(Features & 0x800000)) return FALSE; // no MMX
    return TRUE;
    }

int isAMDK62 (void)
    {
    char Brand [64];
    unsigned int Features;
    // Returns TRUE if processor is an AMD K6 with MMX and 3DNow! or compatible.
    if (!AvailCPUID ()) return FALSE;
    if (FamilyCPUID () < 5) return FALSE;    // not Pentium class or above
    if (FirstCPUID (Brand) < 1) return FALSE;
    if (FirstAMDCPUID () < 0x80000001) return FALSE;
    Features = AMDVersionCPUID ();
    if (!(Features & 0x1)) return FALSE;    // no float
    if (!(Features & 0x800000)) return FALSE; // no MMX
    if (!(Features & 0x80000000)) return FALSE; // no 3DNow!
    return TRUE;
    }

int isAthlon (void)
    {
    char Brand [64];
    unsigned int Features;
    // Returns TRUE if processor is an AMD Athlon with MMX and Advanced 3DNow! or compatible.
    if (!AvailCPUID ()) return FALSE;
    if (FamilyCPUID () < 6) return FALSE;    // not Pentium Pro class or above
    if (FirstCPUID (Brand) < 1) return FALSE;
    if (FirstAMDCPUID () < 0x80000001) return FALSE;
    Features = AMDVersionCPUID ();
    if (!(Features & 0x1)) return FALSE;    // no float
    if (!(Features & 0x8000)) return FALSE; // no CMOV/FCMOV/FCOMI
    if (!(Features & 0x800000)) return FALSE; // no MMX
    if (!(Features & 0x400000)) return FALSE; // no K7 MMX
    if (!(Features & 0x80000000)) return FALSE; // no 3DNow!
    if (!(Features & 0x40000000)) return FALSE; // no Advanced 3DNow!
    return TRUE;
    }

void main (void)
    {
    int Avail, Level;
    unsigned int Features, AMDLevel, AMDFeatures;
    char Brand [64];

    if (AvailCPUID ())
   {
   printf ("CPUID available\n");
   Level = FirstCPUID (Brand);
   printf ("CPUID brand: %s, max eax value: %d\n", Brand, Level);
   if (Level >= 1)
       {
       printf ("Family = %d\n", (FamilyCPUID () >> 8) & 0xF);
       Features = VersionCPUID ();
       if (Features & 1) printf ("Floating-point\n");
       if (Features & 0x8000) printf ("CMOV / FCMOV / FCOMI supported\n");
       if (Features & 0x800000) printf ("MMX supported\n");
       if (Features & 0x2000000)
      {
      printf ("Streaming SIMD Extensions supported by processor\n");
      }
       AMDLevel = FirstAMDCPUID ();
       if (AMDLevel >= 0x80000001)
      {
      AMDFeatures = AMDVersionCPUID ();
      if (AMDFeatures & 0x400000) printf ("AMD K7 MMX Extensions\n");
      if (AMDFeatures & 0x40000000) printf ("AMD K7 3DNow! Extensions\n");
      if (AMDFeatures & 0x80000000) printf ("AMD 3DNow! Extensions\n");
      }
       }
   }
    else
   printf ("CPUID not available - must be 486 or less\n");
    if (isPentium ()) printf ("isPentium\n");
    if (isPentiumMMX ()) printf ("isPentiumMMX\n");
    if (isPentiumPro ()) printf ("isPentiumPro\n");
    if (isPentiumII ()) printf ("isPentiumII\n");
    if (isPentiumIII ()) printf ("isPentiumIII\n");
    if (isAMDK6 ()) printf ("isAMDK6\n");
    if (isAMDK62 ()) printf ("isAMDK62\n");
    if (isAthlon ()) printf ("isAthlon\n");
    }

//////////////////// code end
///////////////////////////////////////////////
User avatar
Volker Pittlik
 
Posts: 1031
Joined: 24 Sep 2004, 10:14
Location: Murten / Morat, Switzerland

Re: CPU detection C code

Postby Jim Ablett » 18 Oct 2004, 17:16

Sorry Volker, still learning!
Jim Ablett
 
Posts: 721
Joined: 27 Sep 2004, 10:39
Location: Essex, England

Re: CPU detection C code

Postby Jim Ablett » 18 Oct 2004, 18:18

Final part of code. (displayed correctly I hope!)

Code: Select all
// --------------  cpuid.h
//
int AvailCPUID (void);
int FirstCPUID (char *s);
int FirstAMDCPUID (void);
unsigned int VersionCPUID (void);
int FamilyCPUID (void);
unsigned int AMDVersionCPUID (void);
int isSSEOS (void);
int isPentium (void);
int isPentiumMMX (void);
int isPentiumPro (void);
int isPentiumII (void);
int isPentiumIII (void);
int isAMDK6 (void);
int isAMDK62 (void);
int isAthlon (void);
//
// ------------   end of code.


The 'is functions are the easiest to use - they will return TRUE for
a processor and its compatible descendants.

isPentium - returns true for Pentiums and compatible.

isPentiumMMX - returns true for Pentiums with MMX and compatible. i.e all
processors with MMX support.

isPentiumPro - returns true for PentiumPros and compatibles (Celeron, Pentium II,
Pentium III and AMD K7)

isPentiumII - returns true for Pentium IIs and compatibles. This is a Pentium Pro
with MMX.

isPentiumIII - returns true for Pentium IIIs and compatibles with operating system
support. This is Pentium II with SSE. This function only returns true
when operating support for SSE is present as this is required for SSE
to function.

isPentium4 - returns true for Pentium 4s and compatibles with operating system
support. These processors support MMX, SSE and SSE2.

isAMDK6 - returns true for AMD K6s with MMX. Some early K6s did not have MMX
support and will return false with this instruction. This is
similar to the isPentiumMMX function, except that it returns false
for Intel CPUs. This is useful to determine scheduling charactistics.

isAMDK62 - returns true for AMD K6-2s and all other processors that support MMX
and 3D Now. No Intel processors currently support 3D Now.

isAthlon - returns true for AMD Athlon and Athlon XP.
Jim Ablett
 
Posts: 721
Joined: 27 Sep 2004, 10:39
Location: Essex, England


Return to Programming and Technical Discussions

Who is online

Users browsing this forum: No registered users and 15 guests