CPUID
cpuid
is an instruction added to Intel Pentiums (and some later 80486's) that enables programmers to determine what kind of features the current
CPU supports, who made it, various extensions and abilities, and cache information.
This article will show you how to get information using
cpuid
, and how to interpret that information to detect support for MMX and its extensions, 3DNow! and its extensions, SSE and its extensions, and some other useful features.
Using CPUID
There are many ways to use
cpuid
, depending on where you are working. There is inline assembly for
GCC and
MSVC (both different), as well as using it in plain assembly files (for
NASM et.al.)
cpuid
uses the value in
eax
, and returns data into
eax, ebx, ecx,
and
edx
. The
eax
input is known as the "Function" input. It can have values from 0x00000000 to 0x00000001, and 0x80000000 to 0x80000008.
To use
cpuid
in GCC, it is normally easiest to just define a macro, like this:
#define cpuid(func,ax,bx,cx,dx)/
__asm__ __volatile__ ("cpuid":/
"=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) : "a" (func));
In the above, you simply put whatever function number you want in for func, and put in 4 variables that will get the output values of
eax, ebx, ecx,
and
edx
, respectively.
int a,b,c,d;
...
cpuid(0,a,b,c,d);
...
In NASM, you simply use the instruction
cpuid
, and handle the outputs as desired. In MSVC, it's a bit longer, but still not too crazy. (Please keep in mind that I don't use MSVC much at all anymore, so this isn't tested).
#define cpuid(func,a,b,c,d)/
asm {/
mov eax, func/
cpuid/
mov a, eax/
mov b, ebx/
mov c, ecx/
mov d, edx/
}
And then you can call it with the same above snippet.
CPUID — Functions
As mentioned above,
cpuid
has many functions, depending on the microprocessor it is on. We'll start from the beginning.
Function 0x00000000:
Function 0 is used to get the Vendor String from the CPU. It also tells us the maximum function supported by
cpuid
. Every
cpuid
-supporting CPU will allow at least this function. I'll describe as many functions as I find information about, but please keep in mind that not all CPUs will handle all function values.
When called,
eax
gets the maximum function call value.
ebx
gets the first 4 bytes of the Vendor String.
edx
gets the second 4 bytes of the Vendor String.
ecx
gets the last 4 bytes of the Vendor String.
When all the Vendor String bytes are lined up, they'll spell a clever phrase depending on who manufactured it.
Intel uses "GenuineIntel",
AMD uses "AuthenticAMD", and
Transmeta uses "GenuineTMx86".
There were other players back in the day, but they seem to have gone out of business or left the CPU market. They were
SiS, Cyrix (now owned by
Via), Centaur (also owned by Via?), NexGen (sold to AMD in 1996),
National Semiconductor (their processor was called the 'Geode'),
UMC (violated Intel patents, so they were never sold Stateside. Seemed to only produce some 486's), and Rise (
IP sold to SiS in 1999).
Function 0x0000001:
Function 0x1 returns the Processor Family, Model, and Stepping information in
eax
.
edx
gets the Standard Feature Flags.
bits (eax) | field |
0-3 | Stepping number |
4-7 | Model number |
8-11 | Family number |
12-13 | Processor Type |
16-19 | Extended Model Number |
20-27 | Extended Family Number |
What we're really interested in is what's in
edx
, the Standard Feature Flags. This register holds a bitmask of all the features needed to determine which SIMD extensions our CPU supports. If we're trying to detect
SSE3, we'll also want to look at
ecx
.
bit (edx) | feature |
18 | PN |
19 | CLFlush |
23 | MMX |
25 | SSE |
26 | SSE2 |
28 | HTT |
Please note that these features are very abridged. There are many other features in the other bits of this register.
Function 0x00000002:
Function 0x2 tells us some information about the processor's cache and
TLB configuration.
Function 0x00000003:
Function 0x3 gets us the bottom 64 bits of the processor's 96 it serial number in
edx:ecx
(if
PN is enabled. This was only used on Pentium III processors. The top 32 bits are the Processor Signature, which is the value of
eax
after executing
cpuid
with
eax
=1 (Function 1).
Function 0x00000004:
Function 0x4 returns some more detailed information about the cache as well as information regarding how many cores the processor has. It looks like Function 0x4 can be used multiplt times to get more information about the various caches the CPU is aware of (?).
Function 0x00000005:
Function 0x5 is used for the
monitor
and
mwait
SSE3 instructions. These are used only by the Operating System, so they're not very useful for user applications.
Function 0x00000006:
Function 0x6 provides us with some information on Power Management and Temperature Control. Again, these are perating System features, and we won't bother with them much here.
While Intel was off making
cpuid
early on, they didn't mention how they planned to use the bits. So when other vendors started making extensions of their own, they needed a way to use
cpuid
to indicate their features without stepping on any toes. To perform this, they use the second function range (0x80000000+). These functions act just like their lower-valued counterparts.
Function 0x80000000:
Function 0x80000000 is just like Function 0, except it returns the highest
Extended function supported. This is probably something like 0x80000008 (at least, for Athlons). The other registers are kept the same (the Vendor String).
Function 0x80000001:
Function 0x80000001 returns values into the same registers as Function 1, but some of the meanings have changed.
eax
gets the Extended Stepping/Mode/Family Numbers.
edx
gets the Extended Feature Flags.
bit (edx) | feature |
22 | AMD MMX Extensions |
30 | 3DNow!2 |
31 | 3DNow! |
Please Note that this is abridged. There are many other features in the other bits of this register.
SSE3:
With later revisions of Intel's Pentium 4 line, they extended SSE2 a bit further. AMD Athlon64's are supposed to support these instructions as well. These new instructions are known as SSE3 or Prescott New Instructions (
PNI).
Please note that SSE extends the way the cpu operates, so not only does the CPU have to support it, but the
OS also needs to support it. The way to detect this varies from system to system.
Windows98 and up support SSE
Linux 2.4 supports SSE (patches for 2.2, if it's not native by now)
Various
BSD flavors have support for SSE as well.
With the above information in hand, detecting available SIMD extensions should be simple.