home *** CD-ROM | disk | FTP | other *** search
- COMMENT $
- This source module contains original INTEL code. It was downloaded
- from the CIS:INTELFORUM on CompuServe by Ernest Vogelsinger,
- CIS ID 100015,551.
-
- Here's the original file description:
-
- CPUID.ZIP/Bin Bytes: 3554, Count: 140, 07-May-91
-
- Title : Intel Recommended CPU/MCP Identification Code
- Keywords: INTEL 386 387 486 487SX
-
- This assembly code file contains the Intel recommended
- technique for properly determining what type of CPU and
- MCP (if any) is installed in the system on which it is run.
-
-
- The following is the header comment of the CPUID.ASM file:
-
- INTEL RECOMMENDED CPU / MCP IDENTIFICATION CODE
-
- The attached CPU / MCP identification assembly code will determine
- which Intel microprocessor and Intel Math CoProcessor (if any) is
- installed in the system. If an Intel486tm microprocessor has been
- recognized, the program will determine if the CPU has a floating
- point unit (Intel486 DX CPU, Intel487tm SX MCP) or not (Intel486
- SX CPU). This code should be executed so the system can be
- configured for a particular application, which may depend on
- the type of microprocessor and math coprocessor installed in
- the system.
-
- History: 91/10/20 EV downloaded from CIS INTEL Forum
- modified to fit to own programming standards
- added code for detection of ProtMode
- on 286/386/486
-
- $
-
- ; Processor and mode bits
- PROC_8086 equ 0001h
- PROC_80286 equ 0002h
- PROC_80386 equ 0004h
- PROC_80486SX equ 0008h
- PROC_80486DX equ 0808h ; 486DX == 486SX+487fp
- PROC_8087 equ 0100h
- PROC_80287 equ 0200h
- PROC_80387 equ 0400h
- PROC_80487 equ 0800h
- MODE_PROTECTED equ 8000h
-
- _DATA segment para public 'DATA'
- fp_status dw 0 ; work variable for coprocessor detection
- ptype dw 0 ; save variable for processor type
- _DATA ends
-
- DGROUP group _DATA
-
- _TEXT segment para public 'CODE'
- assume cs:_TEXT
- assume ds:DGROUP
-
- ; unsigned short far pascal GetCpuId(void);
- public GETCPUID
- GETCPUID proc far
- push bp
- mov bp, sp
- push si
-
- mov si, ptype ; get the processor type
- or si, si
- jz check_8086
-
- jmp check_leave ; already detected: it's not very
- ; likely the processor has
- ; changed since the last time
-
- ;
- ; 8086 CPU check
- ; Bits 12-15 are always set on the 8086 processor.
- ;
- check_8086:
- pushf ; save EFLAGS
- pop bx ; store EFLAGS in BX
- mov ax, 0fffh ; clear bits 12-15
- and ax, bx ; in EFLAGS
- push ax ; store new EFLAGS value on stack
- popf ; replace current EFLAGS value
- pushf ; set new EFLAGS
- pop ax ; store new EFLAGS in AX
- and ax, 0f000h ; if bits 12-15 are set, then CPU
- cmp ax, 0f000h ; is an 8086/8088
- jnz check_286
- or si, PROC_8086
- jmp short check_fpu
-
-
- ;
- ; 80286 CPU check
- ; Bits 12-15 are always clear on the 80286 processor.
- ;
- check_286:
- or bx, 0f000h ; try to set bits 12-15
- push bx
- popf
- pushf
- pop ax
- and ax, 0f000h ; if bits 12-15 are cleared, then CPU
- jnz check_386 ; is an 80286
- or si, PROC_80386
- jmp short check_fpu
-
- ;
- ; i386 CPU check
- ; The AC bit, bit #18, is a new bit introduced in the EFLAGS register
- ; on the i486 DX CPU to generate alignment faults.
- ; This bit can be set on the i486 DX CPU, but not on the i386 CPU.
- ;
- check_386:
- mov bx, sp ; save current stack pointer to align it
- and sp, not 3 ; align stack to avoid AC fault
- db 66h
- pushf ; push original EFLAGS
- db 66h
- pop ax ; get original EFLAGS
- db 66h
- mov cx, ax ; save original EFLAGS
- db 66h ; xor EAX,40000h
- xor ax, 0 ; flip AC bit in EFLAGS
- dw 4 ; upper 16-bits of xor constant
- db 66h
- push ax ; save for EFLAGS
- db 66h
- popf ; copy to EFLAGS
- db 66h
- pushf ; push EFLAGS
- db 66h
- pop ax ; get new EFLAGS value
- db 66h
- xor ax, cx ; if AC bit cannot be changed,
- jnz check_486 ; CPU is 386
- or si, PROC_80386
- jmp short check_fpu
-
- ;
- ; i486 DX CPU / i487 SX MCP and i486 SX CPU checking
- ;
- check_486:
- or si, PROC_80486SX
-
- ;
- ; Co-processor checking begins here for the 8086/80286/i386 CPUs.
- ; The algorithm is to determine whether or not the floating-point status
- ; and control words can be written to.
- ; If they are not, no coprocessor exists.
- ; If the status and control words can be written to, the correct coprocessor
- ; is then determined depending on the processor id.
- ; Coprocessor checks are first performed for an 8086, 80286 and a i486DX CPU.
- ; If the coprocessor id is still undetermined, the system must contain a
- ; i386 CPU. The i386 CPU may work with either an 80287 or an 80387.
- ; The infinity of the coprocessor must be checked to determine the correct
- ; coprocessor id.
- ;
- check_fpu: ; check for 8087/80287/80387
- fninit ; reset FP status word
- mov fp_status, 5a5ah ; initialize temp word to non-zero value
- fnstsw fp_status ; save FP status word
- mov ax, fp_status ; check FP status word
- or al, al ; see if correct status with written
- jnz check_leave ; if not valid, no NPX installed
-
- fnstcw fp_status ; save FP control word
- mov ax, fp_status ; check FP control word
- and ax, 103fh ; see if selected parts looks OK
- cmp ax, 3fh ; check that ones and zeroes correctly read
- jne check_leave ; jump if not Valid, no NPX installed
-
- ; we have a NPX installed
-
- test si, PROC_80486SX ; check if i486 flag is on
- jz @F ; if not, continue with 386 checking
- or si, PROC_80487
- jmp short check_leave
-
- test si, PROC_80386 ; check if i386 flag is on
- jz check_87_287 ; if i386 flag not on, check NPX for
- ; 8086/8088/80286
- ;
- ; 80287/80387 check for the i386 CPU
- ;
- fld1 ; must use default control from FNINIT
- fldz ; form infinity
- fdiv ; 8087/80287 says +inf = -inf
- fld st ; form negative infinity
- fchs ; 80387 says +inf <> -inf
- fcompp ; see if they are the same and remove them
- fstsw fp_status ; look at status from FCOMPP
- mov ax, fp_status
- sahf ; see if infinities matched
- jz @F
- or si, PROC_80387
- jmp short restore_EFLAGS
- @@: or si, PROC_80287
-
- restore_EFLAGS:
- db 66h
- push cx ; push ECX
- db 66h
- popf ; restore original EFLAGS register
- mov sp, bx ; restore original stack pointer
- jmp short check_leave
-
- check_87_287:
- test si, PROC_8086 ; if 8086/8088 flag is on
- jnz @F ; we have an 8087
- or si, PROC_8087
- jmp short check_leave
- @@: or si, PROC_80287 ; else must be an 80287
-
- mov ptype, si ; save the processor type
- ; for next reference
-
- check_leave:
- ; now do the ProtMode check: only 286 and up
- test si, (PROC_80286 or PROC_80386 or PROC_80486SX)
- jz check_exit
-
- .386p
- smsw ax ; get the machine status word
- .286
-
- test ax, 1 ; look if if PM bit set
- jz check_exit
-
- or si, MODE_PROTECTED
-
- check_exit:
- mov ax, si
-
- pop si
- mov sp, bp
- pop bp
- ret
-
- GETCPUID endp
-
-
- _TEXT ends
- end
-
-
-