home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / cpu / cpuid / cpuid.asm next >
Encoding:
Assembly Source File  |  1992-06-01  |  9.2 KB  |  251 lines

  1. COMMENT $
  2.         This source module contains original INTEL code. It was downloaded
  3.         from the CIS:INTELFORUM on CompuServe by Ernest Vogelsinger,
  4.         CIS ID 100015,551.
  5.  
  6.         Here's the original file description:
  7.  
  8.            CPUID.ZIP/Bin   Bytes:   3554, Count:  140, 07-May-91
  9.  
  10.            Title   : Intel Recommended CPU/MCP Identification Code
  11.            Keywords: INTEL 386 387 486 487SX
  12.  
  13.            This assembly code file contains the Intel recommended
  14.            technique for properly determining what type of CPU and
  15.            MCP (if any) is installed in the system on which it is run.
  16.  
  17.  
  18.         The following is the header comment of the CPUID.ASM file:
  19.  
  20.         INTEL RECOMMENDED CPU / MCP IDENTIFICATION CODE
  21.  
  22.         The attached CPU / MCP identification assembly code will determine
  23.         which Intel microprocessor and Intel Math CoProcessor (if any) is
  24.         installed in the system.  If an Intel486tm microprocessor has been
  25.         recognized, the program will determine if the CPU has a floating
  26.         point unit (Intel486 DX CPU, Intel487tm SX MCP) or not (Intel486
  27.         SX CPU).  This code should be executed so the system can be
  28.         configured  for a particular application, which may depend on
  29.         the type of microprocessor and math coprocessor installed in
  30.         the system.
  31.  
  32.         History:   91/10/20 EV downloaded from CIS INTEL Forum
  33.                                modified to fit to own programming standards
  34.                                added code for detection of ProtMode
  35.                                on 286/386/486
  36.  
  37. $
  38.  
  39. ; Processor and mode bits
  40. PROC_8086       equ 0001h
  41. PROC_80286      equ 0002h
  42. PROC_80386      equ 0004h
  43. PROC_80486SX    equ 0008h
  44. PROC_80486DX    equ 0808h ; 486DX == 486SX+487fp
  45. PROC_8087       equ 0100h
  46. PROC_80287      equ 0200h
  47. PROC_80387      equ 0400h
  48. PROC_80487      equ 0800h
  49. MODE_PROTECTED  equ 8000h
  50.  
  51. _DATA segment para public 'DATA'
  52.         fp_status  dw 0           ; work variable for coprocessor detection
  53.         ptype      dw 0           ; save variable for processor type
  54. _DATA ends
  55.  
  56. DGROUP group _DATA
  57.  
  58. _TEXT segment para public 'CODE'
  59.         assume cs:_TEXT
  60.         assume ds:DGROUP
  61.  
  62. ; unsigned short far pascal GetCpuId(void);
  63. public GETCPUID
  64. GETCPUID proc far
  65.         push    bp
  66.         mov     bp, sp
  67.         push    si
  68.  
  69.         mov     si, ptype              ; get the processor type
  70.         or      si, si
  71.         jz      check_8086
  72.  
  73.         jmp     check_leave            ; already detected: it's not very
  74.                                        ; likely the processor has
  75.                                        ; changed since the last time
  76.  
  77. ;
  78. ; 8086 CPU check
  79. ; Bits 12-15 are always set on the 8086 processor.
  80. ;       
  81. check_8086:
  82.         pushf                          ; save EFLAGS
  83.         pop     bx                     ; store EFLAGS in BX
  84.         mov     ax, 0fffh              ; clear bits 12-15
  85.         and     ax, bx                 ;       in EFLAGS
  86.         push    ax                     ; store new EFLAGS value on stack
  87.         popf                           ; replace current EFLAGS value
  88.         pushf                          ; set new EFLAGS
  89.         pop     ax                     ; store new EFLAGS in AX 
  90.         and     ax, 0f000h             ; if bits 12-15 are set, then CPU
  91.         cmp     ax, 0f000h             ;       is an 8086/8088 
  92.         jnz     check_286
  93.         or      si, PROC_8086
  94.         jmp     short check_fpu
  95.  
  96.  
  97. ;
  98. ; 80286 CPU check
  99. ; Bits 12-15 are always clear on the 80286 processor.
  100. ;
  101. check_286:
  102.         or      bx, 0f000h             ; try to set bits 12-15
  103.         push    bx
  104.         popf
  105.         pushf
  106.         pop     ax
  107.         and     ax, 0f000h             ; if bits 12-15 are cleared, then CPU
  108.         jnz     check_386              ;       is an 80286
  109.         or      si, PROC_80386
  110.         jmp     short check_fpu
  111.  
  112. ;
  113. ; i386 CPU check
  114. ; The AC bit, bit #18, is a new bit introduced in the EFLAGS register
  115. ; on the i486 DX CPU to generate alignment faults.
  116. ; This bit can be set on the i486 DX CPU, but not on the i386 CPU.
  117. ;
  118. check_386:
  119.         mov     bx, sp                 ; save current stack pointer to align it
  120.         and     sp, not 3              ; align stack to avoid AC fault
  121.         db      66h
  122.         pushf                          ; push original EFLAGS
  123.         db      66h
  124.         pop     ax                     ; get original EFLAGS 
  125.         db      66h
  126.         mov     cx, ax                 ; save original EFLAGS
  127.         db      66h                    ; xor EAX,40000h
  128.         xor     ax, 0                  ; flip AC bit in EFLAGS
  129.         dw      4                      ; upper 16-bits of xor constant
  130.         db      66h
  131.         push    ax                     ; save for EFLAGS
  132.         db      66h
  133.         popf                           ; copy to EFLAGS
  134.         db      66h
  135.         pushf                          ; push EFLAGS
  136.         db      66h
  137.         pop     ax                     ; get new EFLAGS value
  138.         db      66h
  139.         xor     ax, cx                 ; if AC bit cannot be changed,
  140.         jnz     check_486              ; CPU is 386
  141.         or      si, PROC_80386
  142.         jmp     short check_fpu
  143.  
  144. ;
  145. ; i486 DX CPU / i487 SX MCP and i486 SX CPU checking
  146. ;
  147. check_486:
  148.         or      si, PROC_80486SX
  149.  
  150. ;
  151. ; Co-processor checking begins here for the 8086/80286/i386 CPUs.
  152. ; The algorithm is to determine whether or not the floating-point status
  153. ; and control words can be written to.
  154. ; If they are not, no coprocessor exists.
  155. ; If the status and control words can be written to, the correct coprocessor
  156. ; is then determined depending on the processor id.
  157. ; Coprocessor checks are first performed for an 8086, 80286 and a i486DX CPU.
  158. ; If the coprocessor id is still undetermined, the system must contain a
  159. ; i386 CPU.  The i386 CPU may work with either an 80287 or an 80387.
  160. ; The infinity of the coprocessor must be checked to determine the correct
  161. ; coprocessor id. 
  162. ;
  163. check_fpu:                             ; check for 8087/80287/80387
  164.         fninit                         ; reset FP status word
  165.         mov     fp_status, 5a5ah       ; initialize temp word to non-zero value
  166.         fnstsw  fp_status              ; save FP status word
  167.         mov     ax, fp_status          ; check FP status word
  168.         or      al, al                 ; see if correct status with written
  169.         jnz     check_leave            ; if not valid, no NPX installed
  170.  
  171.         fnstcw  fp_status              ; save FP control word
  172.         mov     ax, fp_status          ; check FP control word 
  173.         and     ax, 103fh              ; see if selected parts looks OK
  174.         cmp     ax, 3fh                ; check that ones and zeroes correctly read
  175.         jne     check_leave            ; jump if not Valid, no NPX installed
  176.  
  177. ; we have a NPX installed
  178.  
  179.         test    si, PROC_80486SX       ; check if i486 flag is on
  180.         jz      @F                     ; if not, continue with 386 checking
  181.         or      si, PROC_80487
  182.         jmp     short check_leave
  183.  
  184.         test    si, PROC_80386         ; check if i386 flag is on
  185.         jz      check_87_287           ; if i386 flag not on, check NPX for
  186.                                        ;       8086/8088/80286
  187. ;
  188. ; 80287/80387 check for the i386 CPU
  189. ;
  190.         fld1                           ; must use default control from FNINIT
  191.         fldz                           ; form infinity
  192.         fdiv                           ; 8087/80287 says +inf = -inf
  193.         fld     st                     ; form negative infinity
  194.         fchs                           ; 80387 says +inf <> -inf
  195.         fcompp                         ; see if they are the same and remove them
  196.         fstsw   fp_status              ; look at status from FCOMPP
  197.         mov     ax, fp_status
  198.         sahf                           ; see if infinities matched
  199.         jz      @F
  200.         or      si, PROC_80387
  201.         jmp     short restore_EFLAGS
  202. @@:     or      si, PROC_80287
  203.  
  204. restore_EFLAGS:
  205.         db      66h
  206.         push    cx                     ; push ECX
  207.         db      66h
  208.         popf                           ; restore original EFLAGS register
  209.         mov     sp, bx                 ; restore original stack pointer
  210.         jmp     short check_leave
  211.  
  212. check_87_287:
  213.         test    si, PROC_8086          ; if 8086/8088 flag is on
  214.         jnz     @F                     ;       we have an 8087
  215.         or      si, PROC_8087
  216.         jmp     short check_leave
  217. @@:     or      si, PROC_80287         ;       else must be an 80287
  218.  
  219.         mov     ptype, si              ; save the processor type
  220.                                        ; for next reference
  221.  
  222. check_leave:
  223. ; now do the ProtMode check: only 286 and up
  224.         test    si, (PROC_80286 or PROC_80386 or PROC_80486SX)
  225.         jz      check_exit
  226.  
  227. .386p
  228.         smsw    ax                     ; get the machine status word
  229. .286
  230.  
  231.         test    ax, 1                  ; look if if PM bit set
  232.         jz      check_exit
  233.  
  234.         or      si, MODE_PROTECTED
  235.  
  236. check_exit:
  237.         mov     ax, si
  238.  
  239.         pop     si
  240.         mov     sp, bp
  241.         pop     bp
  242.         ret
  243.  
  244. GETCPUID endp
  245.  
  246.  
  247. _TEXT ends
  248. end
  249.  
  250.  
  251.