Article View: comp.os.msdos.programmer
Article #1962Re: Re: Detecting an 80486
From: Andrew Rossmann
Date: Tue, 21 Aug 1990 22:34
Date: Tue, 21 Aug 1990 22:34
507 lines
13566 bytes
13566 bytes
In article <3839@altos86.Altos.COM> rcollins@altos86.UUCP (Robert Collins) writes:
>In article <9008161307.AA11621@esegue.segue.boston.ma.us> johnl@esegue.segue.boston.ma.us (John R. Levine) writes:
>>
>>can't try it myself.) If flag bit 18 really doesn't work, it might work to
>>try wiggling bit 18 in CR0 which is unimplemented on the 386.
>>
>
>You can't access CR0 in CPL3. So setting any bit in CR0 in V86 mode will
>be trapped. I have tried setting bit18 in EFLAGS, and found it not to
>be latched in real mode. I found this astonishing, and therefore posted
>my results. Since that posting I did further testing, and found my first
>conclusion to be wrong.
I just took a 'peek' at Nortons SI, version 5 (the new one). It detects
the '486 by fiddling with bit 18! So, apparantly, they must think it's OK,
although I should think they have probably tested it, too.
What follows is the latest version of the CPU/NDP code from INFOPLUS.
I've slightly tweaked the '486 detection, and further changed the NDP
detection. I hope to get that problem fixed soon, if this doesn't do it.
Some people have said that the 386 w/ AMI BIOS and no 387 is giving the
most problems.
Andrew Rossmann
andyross@ddsw1.MCS.COM
P.S.> Version 1.3 of INFOPLUS is still under development.
;--------------------------------------------------------------------
;
; INFOPLUS.ASM
;
; Version 1.30
;
; Four subprograms used by INFOPLUS.PAS:
;
; CPUID - identifies host CPU and NDP (if
; any)
; DISKREAD - reads absolute sectors from disk
; LONGCALL - calls a routine using a CALL FAR
; ATIINFO - for accessing ATI VGAWonder cards
;
; Originally by:
; Steve Grant
; Long Beach, CA
; January 13, 1989
;
; mods by Andrew Rossmann (8/19/90)
;--------------------------------------------------------------------
.286P
.8087
public CPUID, DISKREAD, LONGCALL, ATIINFO, AltIntr
CODE segment byte
; Conditional jumps are all coded with the SHORT qualifier in
; order to minimize the size of the .OBJ file output of Turbo
; Assembler.
;--------------------------------------------------------------------
CPUID proc near
assume cs:CODE, ds:DATA, es:nothing, ss:nothing
; On entry:
;
; BP
; SP => near return address
; offset of a cpu_info_t record
; segment " " " "
; also, the test type byte should be 'C', 'N' or 'W' to execute the
; CPU or NDP or Weitek tests.
;
; On exit, the cpu_info_t record has been filled in as follows:
;
; byte = CPU type
; word = Machine Status Word
; 6 bytes = Global Descriptor Table
; 6 bytes = Interrupt Descriptor Table
; boolean = segment register change/interrupt flag
; byte = NDP type
; word = NDP control word
; byte = Weitek presence
; byte = test type (C, N, or W)
mCPU equ byte ptr [bx]
mMSW equ word ptr [bx + 1]
mGDT equ [bx + 3]
mIDT equ [bx + 9]
mchkint equ byte ptr [bx + 15]
mNDP equ byte ptr [bx + 16]
mNDPCW equ word ptr [bx + 17]
mWeitek equ byte ptr [bx + 19]
mtest equ byte ptr [bx + 20]
f8088 equ 0
f8086 equ 1
fV20 equ 2
fV30 equ 3
f80188 equ 4
f80186 equ 5
f80286 equ 6
f80386 equ 7
f80486 equ 8
funk = 0FFH
false equ 0
true equ 1
push bp
mov bp,sp
push ds
lds bx,[bp + 4]
cmp mtest, 'C'
jnz skipcpu
call cpu
call chkint
skipcpu:
cmp mtest, 'N'
jnz skipndp
call ndp
skipndp:
cmp mtest, 'W'
jnz skipweitek
call weitek
skipweitek:
pop ds
pop bp
ret 4
;--------------------------------------------------------------------
cpu:
; interrupt of multi-prefix string instruction
mov mCPU,funk ;set CPU type to unknown
sti
mov cx,0FFFFH
rep lods byte ptr es:[si]
jcxz short cpu_02
call piq
cmp dx,4
jg short cpu_01
mov mCPU,f8088
ret
cpu_01:
cmp dx,6
jne short cpu_01a
mov mCPU,f8086
cpu_01a:
ret
cpu_02:
; number of bits in displacement register used by shift
mov al,0FFH
mov cl,20H
shl al,cl
or al,al
jnz short cpu_04
call piq
cmp dx,4
jg short cpu_03
mov mCPU,fV20
ret
cpu_03:
cmp dx,6
je cpu_03a
jmp CPUID_done
cpu_03a:
mov mCPU,fV30
ret
cpu_04:
; order of write/decrement by PUSH SP
push sp
pop ax
cmp ax,sp
je short cpu_06
call piq
cmp dx,4
jg short cpu_05
mov mCPU,f80188
ret
cpu_05:
cmp dx,6
jne short CPUID_done
mov mCPU,f80186
ret
;First, grab some tables
cpu_06:
smsw mMSW
sgdt mGDT
sidt mIDT
;!!!!!!!
;!!! Original 286/386 detection code (modified 8/10/90)
;!!! Modified by code supplied by John Levine, apparantly from an Intel
;!!! '486 manual.
;!!!!!!!
pushf ;put flags into CX
pop cx
and cx,0fffh ;mask off upper 4 bits
push cx
popf
pushf
pop ax
and ax,0f000h ;look only at upper 4 bits
cmp ax,0f000h ;88/86 etc.. turn them on
jz badcpu ;not 286/386/486!!!
or cx,0f000h ;force upper 4 bits on
push cx
popf
pushf
pop ax
and ax,0f000h
jz found286 ;bits are zeroed in real mode 286
;
;since we probably have have a 386 or 486 by now, we need to do some 32-bit
;work. Detect the 486 by seeing if the Alignment Check flag is settable. This
;flag only exists on the '486.
;
.386
and esp,0FFFFh ;use only 64K stack
mov edx,esp ;save current stack position
and esp,0FFFCh ;dword align to avoid traps
pushfd ;push 32 bit flag
pop eax
mov ecx,eax ;save current flags
xor eax,40000h ;flip AC (alignment check) flag
push eax
popfd
pushfd
pop eax
xor eax,ecx ;eliminate all but AC bit
push ecx ;restore flags
popfd
mov esp,edx ;restore stack position
test eax,40000h ;is bit set?
.286
jz found386 ;if not, is a 386
mov mCPU,f80486 ;must be a 486!!
jmp short CPUID_done
found286:
mov mCPU,f80286
jmp short CPUID_done
found386:
mov mCPU,f80386
jmp short CPUID_done
badcpu:
mov mCPU,funk ;how'd an 8088 get this far?????
CPUID_done:
ret
;--------------------------------------------------------------------
piq:
; On exit:
;
; DX = length of prefetch instruction queue
;
; This subroutine uses self-modifying code, but can
; nevertheless be run repeatedly in the course of the calling
; program.
count = 7
opincdx equ 42H ; inc dx opcode
opnop equ 90H ; nop opcode
mov al,opincdx
mov cx,count
push cx
push cs
pop es
mov di,offset piq_01 - 1
push di
std
rep stosb
mov al,opnop
pop di
pop cx
xor dx,dx
cli
rep stosb
rept count
inc dx
endm
piq_01:
sti
ret
;--------------------------------------------------------------------
chkint:
; save old INT 01H vector
push bx
mov ax,3501H
int 21H
mov old_int01_ofs,bx
mov old_int01_seg,es
pop bx
; redirect INT 01H vector
push ds
mov ax,2501H
mov dx,seg new_int01
mov ds,dx
mov dx,offset new_int01
int 21H
pop ds
; set TF and change SS -- did we trap on following instruction?
pushf
pop ax
or ah,01H ; set TF
push ax
popf
push ss ; CPU may wait one
; instruction before
; recognizing single step
; interrupt
pop ss
chkint_01: ; shouldn't ever trap here
; restore old INT 01H vector
push ds
mov ax,2501H
lds dx,old_int01
int 21H
pop ds
ret
;--------------------------------------------------------------------
new_int01:
; INT 01H handler (single step)
;
; On entry:
;
; SP => IP
; CS
; flags
sti
pop ax ; IP
cmp ax,offset chkint_01
jb short new_int01_03
je short new_int01_01
mov mchkint,false
jmp short new_int01_02
new_int01_01:
mov mchkint,true
new_int01_02:
pop cx ; CS
pop dx ; flags
and dh,0FEH ; turn off TF
push dx ; flags
push cx ; CS
new_int01_03:
push ax ; IP
iret
;--------------------------------------------------------------------
ndp:
fnone equ 0
f8087 equ 1
f80287 equ 2
f80387 equ 3
funk = 0FFH
mov word ptr ndp_cw,0000H
cli
; The next two 80x87 instructions cannot carry the WAIT prefix,
; because there may not be an 80x87 for which to wait. The WAIT is
; therefore emulated with a MOV CX,<value>! LOOP $ combination.
.287
cli ;no interrupts during this test
;
; if there are problems, try uncommenting the following lines
; xor ax,ax
; out 0f0h,al
finit ;initialize NDP
mov cx,2
loop $
fstcw ndp_cw ;store status word in ndp_cw
mov cx,14h
loop $
sti
mov ax,ndp_cw ;check for valid status word
cmp ah,3 ;is NDP present?
je short ndp_01 ;if 3, must be there
mov mNDP,fnone
jmp short ndp_done
ndp_01:
cmp ax,03FFH ;check if 8087
jne short ndp_02
mov mNDP,f8087
jmp short ndp_04
ndp_02:
.287
cmp ax,037FH ;check if 286/387/486
jne short ndp_05 ;must be garbage
;detect 287 or 387
fld1 ;Load +1.0 onto NDP stack
fldz ;Load +0.0 onto NDP stack
fdiv ;do +1/0
fld1 ;Load +1.0 onto NDP stack
fchs ;Change to -1.0
fldz ;Load +0.0 onto NDP stack
fdiv ;do -1/0
fcom ;compare
fstsw ndp_sw
mov ax,ndp_sw
and ah,41H ; C3, C0
cmp ah,40H ; ST(0) = ST(1)
jne short ndp_03
mov mNDP,f80287
jmp short ndp_04
ndp_03:
cmp ah,01H ; ST(0) < ST(1)
jne short ndp_05
mov mNDP,f80387
ndp_04:
.8087
fstcw mNDPCW ;save status for INFOPLUS
ret
ndp_05:
mov mNDP,funk
ndp_done:
ret
; This checks to see if the BIOS reports a Weitek math coprocessor. This should
; only be called if a 386 or 486 is found.
; NOTE!! This may not work with all computers!!
fnoWeitek equ 0
fWeitek equ 1
fWeitek_real equ 81h
weitek:
.386
xor eax,eax ;zero everything
int 11h ;do equipment check
test eax,01000000h ;check bit 24, set if Weitek present
je no_weitek
mov mWeitek,fWeitek
test eax,0800000h ;check bit 23, set if Weitek can be
je weitek_done ; addressed in real mode
mov mWeitek,fWeitek_real
jmp short weitek_done
no_weitek:
mov mWeitek,fnoWeitek
weitek_done:
ret
.286
CPUID endp
code ends
;--------------------------------------------------------------------
DATA segment byte
; storage for CPUID
; redirected INT 01H vector
old_int01 label dword
old_int01_ofs dw ?
old_int01_seg dw ?
; storage for NDPID
; 80x87 control word after initialization, status word after divide by zero
ndp_cw dw ?
ndp_sw dw ?
DATA ends
end
Technical Details
Message-ID:
<1990Aug21.223404.19523@ddsw1.MCS.COM>Path:
arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!rutgers!mcdchg!ddsw1!andyrossReferences:
<26a858b9@ralf> <3817@altos86.Altos.COM> <1990Aug14.025550.17669@esegue.segue.boston.ma.us> <OTTO.90Aug15022916@tukki.jyu.fi> < <3839@altos86.Altos.COM>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!rutgers!mcdchg!ddsw1!andyross From: andyross@ddsw1.MCS.COM (Andrew Rossmann) Newsgroups: comp.os.msdos.programmer Subject: Re: Re: Detecting an 80486 Message-ID: <1990Aug21.223404.19523@ddsw1.MCS.COM> Date: 21 Aug 90 22:34:04 GMT References: <26a858b9@ralf> <3817@altos86.Altos.COM> <1990Aug14.025550.17669@esegue.segue.boston.ma.us> <OTTO.90Aug15022916@tukki.jyu.fi> < <3839@altos86.Altos.COM> Reply-To: andyross@ddsw1.MCS.COM (Andrew Rossmann) Organization: ddsw1.MCS.COM Contributor, Wheeling, IL Lines: 507