[Home] [Identification] [Programming] [Sitemap]

JavaScript Tree Menu

x86 Identification Routines

 


There are several methods for identifying CPUs. For this documentation, I will concentrate on how to detect different 32-bit processors (as that is all that I am targetting for my OS). This page also includes some information on detecting 8 and 16-bit processors, although I don't believe it to be complete.


Early processor identification:

CPU Method
808x/186+ Shift register by 32. Clears register on 808x and NEC V2/30.
This is because later CPUs mask shift/rotate value with 01Fh.
808x/NEC PUSHA;
NOP;

pusha is executed on V20/30, so we can check if SP has changed.
On 808x, pusha executes as a 2-byte nop, so SP is not changed.
808x/80C8x REP ES: MOVSB ; CX = 0FFFFh
Test within a loop.
If CX is non-zero at the end of a loop, then it is a NMOS chip.
If always zero, it is CMOS.
18x/286 PUSH SP
On 286 and later, the original value of SP is stored.
On 18x and earlier, the new value is stored.
8/16-bit Use self-modifying code (808x/8018x/Vx0)
The prefetch queue on 8-bit processors is 4 bytes long.
The prefetch queue on 16-bit processors is 6 bytes long.
For example, change a NOP to an INC. If executed as INC, we we have an 8-bit processor.
286/3 86+ Test behaviour of flags[12-15].
808x and 8018x flags[12-15] are always set.
286 flags[12-15] are always clear in real-address mode.
32-bit processors: real-mode bit 15 is always clear;
bits 12-14 have the last value loaded into them.
32-bit processors: protected mode bit 15 is always clear;
bit 14 has the last value loaded into it;
and the IOPL bits depends on the (CPL).
The IOPL field can be changed only if the CPL is 0.



32-bit processor identification

CPU Method
486 Eflags[18] can be changed on 486 and later processors.
386DX To determine the stepping of 386DX:
Stepping B0 and earlier support IBTS/XBTS, later don't.
Stepping B1, rep insb with CX=1 doesn't clear CX
NexGen Nx586 When we know it's a 386 (and not a 486), we can do a div test:
xor ax,ax ; clear ax
sahf ; clear flags,
; bit 1 of flags is always set
mov ax,5 ; move 5 into the dividend
xor dx,dx
mov bx,2 ; move 2 into the divisor
div bl ; perform div test
jz is_NexGen ; flags not changed,
; it's a NexGen CPU
ZF will never be set on a NexGen CPU, but will be set on others.

To detect CPUID on a NexGen processor, it has to be done using a #UD handler.
NexGen chips don't always have the ID Flag, and CPUID is handled by the BIOS.
386SX/DX
(Also Cx486SLC/DLC)
If CR0 bit 4 can be cleared, we have a 386, 386DX or Cx486DLC.
If it cannot be cleared, it is a 386SX, 486SLC or a 'real' 486.
Always restore CR0 (MSW) after this test.
i386 EX has 64M memory space
SX has 16M memory space
DX has 4G memory space
Am386SX/SXL/SXLV If you can execute SMM instructions, it's an SXLV.
C&T 386's This involves a test for the 386 POPAD bug.
The 386 POPAD bug affects all 386DX and early 386SX revisions.
I don't have any complete documentation for this, only what
Ralf Brown's Interrupt List says.
Psuedo-code:
Set EAX=12345678h ; value that won't roate to same value.
set i = 32
DO{
set EBX = EAX
clear EDX and EDI
push all and pop all (32-bit)
set ECX = [EDX + EDI]
IF(EAX <> EBX) exit loop.
rotate EAX left by 1
decrement i
} WHILE(i > 0)
If i = 0, we have a C&T 386, otherwise it's an AMD or Intel.
CPUID Eflags[21] can be changed on processors which support CPUID.
Cyrix Finds Cyrix, TI, SGS, IBM processors.
First check that it is a 486+, then:
Method 1: For pre-Pentium and non-SMI modes:
UMOV executed as double NOP on Cyrix processors.
Method 2: Divide test:
Store 0 to flags low byte (bit 1 always set).
Divide 5 (in AX) by 2 (Cyrix show it in BL).
Read low byte of flags (LAHF).
If not equal to 2, it's not a Cyrix processor.
If this test detects a Cyrix chip, CPUID must be enabled before use.
This is done by setting CPUIDEN (CCR4 bit 7).
See the section on Cyrix detection for more info on this.
IBM 386/486 SLC, 486BL3 (others??)
Test initially as 486 and Cyrix.
IBM 386 and some 486 use MSRs.
UMC I'm not sure what this does. I got it from RBIL.
Use this for UMC U486SX. For other UMC processors, use CPUID.
db 64h,0d6h


cmp eax,0ab6b1b07h
je u486SX
jne Other

; looks like "SALC FS:", but it's not.
; OPCODES.LST with RBIL says "db 64h,0dbh"
; which is not SALC FS
; "umctest.c" from Herbert Oppmann confirms
; the values I have used.

FPU Test for FPU:
Clear a 16-bit memory area [mem]
Initialise FPU (perform FNINIT)
Store FPU control word to [mem] (perform FNSTCW [mem])
If [mem] is 037Fh, then we have an FPU present.
SMM Use UMOV to test for SMM enabled and SL enhanced AMD 386/486s, and IBM 486SLC2.
If no SMM, it will generate a #UD.
Cyrix executed this as a double nop.
Only use this test on 386/486, and make sure it's not a UMC processor first, as they will hang.