streich@boulder.Colorado.EDU (Mark Streich) (07/23/90)
Here is a slightly changed version of James Howard's (of Dell Computer Corp)
processor detection program. It works in Turbo Pascal. (at least in 5.5,
which I was able to check) As I only have a '386 immediately available,
could someone else report on how it works on the other processors. It
did work with QEMM, by the way.
It should work with any other compiler which expects integer function
results to be returned in the AX register.
Instead of printing a message, as Howard's version did, this is a function
returning an integer that represents the type of processor on the machine.
============================================================================
Unit Detect;
Interface
Function DetectCPU : Integer;
{ Returns: 86 (8086/8), 186 (80186/8), 286 (80286), or 386 (80386) }
Implementation
Function DetectCPU : Integer; external;
{$L Detect}
end.
============================================================================
;
; CPU.ASM -- Determine CPU Type on any IBM or Compatible
;
; DESCRIPTION: Uses particular unique attributes of 8088/86, 80188/86,
; 80286, and 80386 Microprocessors to determine CPU type
; during runtime. This is useful to enable specialized
; routines to take advantage of enhanced instructions if
; available.
;
; Notes:
;
; 8088/86
; This CPU has a unique way of handling the instruction PUSH SP,
; which is commonly tested from software with three instructions.
; 80188/86
; However, it does not help in determining the existence of a
; 80186/88 processor, because it is the same as the 80286 in the
; way it handles PUSH SP. Instead, there is a common difference
; in that the flag register is handled differently. If bits 12-15
; are always held high, it is either an 808x or 8018x processor.
; To decide which it is after this is tested, the way the SHL CX
; instruction is handled can be used. On an 808x, if CX > 32 it
; will go ahead and shift it around anyway. On an 80x8x, the high
; order is masked off, so SHL CX with CX=35 will really only shift
; 3 (35-32).
; 80286
; Once you know it is not a 808x, you need to determine if it is an
; 80286 or 80386 processor. This again can be determined by looking
; at the flags register. If bits 12-14 are forced low, it is a 286.
; 80386
; If it falls through, it must be an 80386 by default.
;
code segment byte public
assume cs:code
DetectCPU proc far
public DetectCPU
xor ax,ax ; zero AX
push ax
popf ; pop AX(=0) into flags
pushf
pop ax ; pop AX
and ax,0f000h ; see if bits tied high
cmp ax,0f000h ; for 8088/186
jz is_0_1 ; a 8018x or 808x
mov ax,07000h ; see if 12-14 tied low
push ax
popf
pushf
pop ax
and ax,07000h ; if 12-14 are 0
jz is_80286 ; then is 80286
is_80386:
mov ax,386 ; else it's a 80386
jmp short return
is_80286:
mov ax,286 ; it's a 80286
jmp short return
is_0_1:
push cx
mov ax,0ffffh ; set to all ones
mov cl,33 ; try to shift more than 32
shl ax,cl ; 808x will shift all bits out
jnz is_80186 ; nonzero bit means 8018x
is_8086:
mov ax,86
pop cx
jmp short return
is_80186:
mov ax,186
pop cx
return: retf
DetectCPU endp
code ends
end