208 lines
8.7 KiB
NASM
208 lines
8.7 KiB
NASM
|
; calling convention:
|
||
|
;
|
||
|
; int chips( void );
|
||
|
;
|
||
|
; returns:
|
||
|
;
|
||
|
; tucked away neatly in your AX....
|
||
|
;
|
||
|
; you get back 8x if an 8088/8086
|
||
|
; 18x if an 80186/80188
|
||
|
; 28x if an 80286
|
||
|
; 38x if an 80386
|
||
|
; 20x for a NEC V20/V30
|
||
|
; AND
|
||
|
; xx0 if NO NDP is found
|
||
|
; xx1 if an 8087
|
||
|
; xx2 if an 80287
|
||
|
; xx3 for an 80387
|
||
|
;
|
||
|
; OR.....
|
||
|
;
|
||
|
; >>> A return of 280 means you got an 80286 machine with no NDP, <<<
|
||
|
; >>> 383 means you have an 80386/80387 rig to work with, and a <<<
|
||
|
; >>> return of 81 sez that you have 8088/8086 CPU with an 8087. <<<
|
||
|
; >>> A 200 tells you that you got an NEC V20/V30 without an NDP. <<<
|
||
|
; >>> ETC., Etc., etc. <<<
|
||
|
;
|
||
|
; NOTE:
|
||
|
;
|
||
|
; There are lotsa ways of handling the way this function returns
|
||
|
; it's data. For my purposes, I have elected this one because
|
||
|
; it requires only int arithmetic on the caller's end to extract
|
||
|
; all the info I need from the return value. I think that I'm
|
||
|
; well enough 'commented' in the following code so that you will
|
||
|
; be able to tinker and Putz until you find the best return tech-
|
||
|
; nique for Ur purposes without having to reinvent the wheel.
|
||
|
;
|
||
|
; >>>> Please see TEST.C, enclosed in this .ARC. <<<<
|
||
|
;
|
||
|
; REFERENCES:
|
||
|
;
|
||
|
; _chips is made up of two PROC's, cpu_type and ndp_type.
|
||
|
;
|
||
|
; cpu_type is based on uncopyrighted, published logic by
|
||
|
; Clif (that's the way he spells it) Purkiser of Intel -
|
||
|
; Santa Clara.
|
||
|
;
|
||
|
; ndp_type is adopted from Ted Forgeron's article in PC
|
||
|
; Tech Journal, Aug '87 p43.
|
||
|
;
|
||
|
; In the event of subsequent republication of this function,
|
||
|
; please carry forward reference to these two gentlemen as
|
||
|
; original authors.
|
||
|
;
|
||
|
.MODEL SMALL
|
||
|
.CODE
|
||
|
PUBLIC _chips
|
||
|
|
||
|
_chips PROC
|
||
|
|
||
|
control dw 0 ; control word needed for the NDP test
|
||
|
|
||
|
push BP ; save where Ur at
|
||
|
mov BP,SP ; going in.....
|
||
|
|
||
|
push DI
|
||
|
push SI
|
||
|
push CX ; not really needed for MSC but kinda
|
||
|
; nice to do cuz someone else might
|
||
|
; want to use the function and we do
|
||
|
; use CX later on
|
||
|
|
||
|
call cpu_type ; find out what kinda CPU you got and
|
||
|
; and save it in DX for future reference
|
||
|
call ndp_type ; check for math coprocessor (NDP) type
|
||
|
; and hold that result in AX
|
||
|
|
||
|
add AX,DX ; add the two results together and hold
|
||
|
; 'em in AX for Ur return to the caller
|
||
|
|
||
|
pop CX ; put things back the way that you
|
||
|
pop SI ; found 'em when you started this
|
||
|
pop DI ; little drill off.....
|
||
|
pop BP
|
||
|
; AND
|
||
|
ret ; go back to where you came from....
|
||
|
; ( ===> the calling program )
|
||
|
; with Ur results sittin' in AX !!
|
||
|
_chips endp
|
||
|
|
||
|
|
||
|
cpu_type PROC
|
||
|
|
||
|
pushf ; pump Ur flags register onto the stack
|
||
|
xor DX,DX ; blow out Ur DX and AX to start off
|
||
|
xor AX,AX ; with a clean slate
|
||
|
push AX ; put AX on the stack
|
||
|
popf ; bring it back in Ur flags
|
||
|
pushf ; try to set bits 12 thru 15 to a zero
|
||
|
pop AX ; get back Ur flags word in AX
|
||
|
and AX, 0f000h ; if bits 12 thru 15 are set then you got
|
||
|
cmp AX, 0f000h ; an Intel 8018x or a 808x or maybe even
|
||
|
jz dig ; a NEC V20/V30 ??? - gotta look more...
|
||
|
|
||
|
; OTHERWISE....
|
||
|
; Here's the BIG one.... 'tells the difference between an 80286 and
|
||
|
; an 80386 !!
|
||
|
|
||
|
mov AX, 07000h ; try to set FLAG bits 12 thru 14
|
||
|
; - NT, IOPL
|
||
|
push AX ; put it onto the stack
|
||
|
popf ; and try to pump 07000H into Ur flags
|
||
|
pushf ; push Ur flags, again
|
||
|
pop AX ; and bring back AX for a compare
|
||
|
and AX,07000h ; if Ur bits 12 thru 14 are set
|
||
|
jnz got386 ; then Ur workin' with an 80386
|
||
|
mov DX, 0280 ; save 280 in DX cuz it's an 80286
|
||
|
jmp SHORT CPUbye ; and bail out
|
||
|
|
||
|
got386: mov DX, 0380 ; save 380 in DX cuz it's an Intel 80386
|
||
|
jmp SHORT CPUbye ; and bail out
|
||
|
|
||
|
; here's we try to figger out whether it's an 80188/80186, an 8088/8086
|
||
|
; or an NEC V20/V30 - 'couple of slick tricks from Clif Purkiser.....
|
||
|
|
||
|
dig: mov AX, 0ffffh ; load up AX
|
||
|
mov CL, 33 ; HERE's the FIRST TRICK.... this will
|
||
|
; shift everything 33 times if it's
|
||
|
; 8088/8086, or once for a 80188/80186!
|
||
|
shl AX, CL ; on a shift of 33, all bits get zeroed
|
||
|
jz digmor ; out so if anything is left ON it's
|
||
|
; gotta be an 80188/80186
|
||
|
mov DX,0180 ; save 180 in DX cuz it's an 80188/80186
|
||
|
jmp SHORT CPUbye ; and bail out
|
||
|
|
||
|
digmor: xor AL,AL ; clean out AL to set ZF
|
||
|
mov AL,40h ; ANOTHER TRICK.... mul on an NEC duz NOT
|
||
|
mul AL ; effect the zero flag BUT on an Intel
|
||
|
jz gotNEC ; 8088/8086, the zero flag gets thrown
|
||
|
mov DX,0080 ; 80 into DX cuz it's an Intel 8088/8086
|
||
|
jmp SHORT CPUbye ; and bail out
|
||
|
|
||
|
gotNEC: mov DX,0200 ; it's an NEC V20/V30 so save 200 in DX
|
||
|
|
||
|
CPUbye: popf ; putchur flags back to where they were
|
||
|
ret ; and go back to where you came from
|
||
|
; (i.e., ===> _chips) with the CPU type
|
||
|
; tucked away in DX for future reference
|
||
|
cpu_type endp
|
||
|
|
||
|
; Check for an NDP.
|
||
|
;
|
||
|
; >>>>NOTE: If you are using an MASM version < 5.0, don't forget to
|
||
|
; use the /R option or you will bomb cuz of the coprocessor instruc-
|
||
|
; tions. /R is not needed for version 5.0.<<<<<<<<<<<<<<<<<<<<<<<<<
|
||
|
|
||
|
ndp_type PROC
|
||
|
|
||
|
do_we: fninit ; try to initialize the NDP
|
||
|
mov byte ptr control+1,0 ; clear memory byte
|
||
|
fnstcw control ; put control word in memory
|
||
|
mov AH,byte ptr control+1 ; iff AH is 03h, you got
|
||
|
cmp AH,03h ; an NDP on board !!
|
||
|
je chk_87 ; found somethin', keep goin'
|
||
|
xor AX,AX ; clean out AX to show a zero
|
||
|
jmp SHORT NDPbye ; return (i.e., no NDP)
|
||
|
|
||
|
; 'got an 8087 ??
|
||
|
|
||
|
chk_87: and control,NOT 0080h ; turn ON interrupts (IEM = 0)
|
||
|
fldcw control ; load control word
|
||
|
fdisi ; turn OFF interrupts (IEM = 1)
|
||
|
fstcw control ; store control word
|
||
|
test control,0080h ; iff IEM=1, 8087
|
||
|
jz chk287 ; 'guess not! March on....
|
||
|
mov AX,0001 ; set up for a 1 return to
|
||
|
jmp SHORT NDPbye ; show an 8087 is on board
|
||
|
|
||
|
; if not.... would you believe an 80287 maybe ??
|
||
|
|
||
|
chk287: finit ; set default infinity mode
|
||
|
fld1 ; make infinity
|
||
|
fldz ; by dividing
|
||
|
fdiv ; 1 by zero !!
|
||
|
fld st ; now make a
|
||
|
fchs ; negative infinity
|
||
|
fcompp ; compare Ur two infinities
|
||
|
fstsw control ; iff, for 8087 or 80287
|
||
|
fwait ; sit tight 'til status word is put away
|
||
|
mov AX,control ; getchur control word
|
||
|
sahf ; putchur AH into flags
|
||
|
jnz got387 ; NO GOOD.... march on !!
|
||
|
mov AX,0002 ; gotta be a 80287 cuz we already tested
|
||
|
jmp SHORT NDPbye ; for an 8087
|
||
|
|
||
|
; We KNOW that there is an NDP on board otherwise we would have bailed
|
||
|
; out after 'do_we'. It isn't an 8087 or an 80287 or we wouldn't have
|
||
|
; gotten this far. It's gotta be an 80387 !!
|
||
|
|
||
|
got387: mov AX,0003 ; call it an 80387 and return 3
|
||
|
|
||
|
NDPbye: ret ; and go back where you came from
|
||
|
; (i.e., ===> _chips) carrying the NDP
|
||
|
; type in Ur AX register
|
||
|
ndp_type endp
|
||
|
|
||
|
_text ends
|
||
|
end
|