home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / basic / library / qb_pds / dcpu / masm / cpu_ty.asm next >
Encoding:
Assembly Source File  |  1994-06-17  |  23.6 KB  |  592 lines

  1. ; Created 04/17/92
  2. ; updated 07/22/93
  3. ;       updated 02/05/94 information about IBM 486SLC2 chips
  4. ;    updated 02/28/94 information about Cyrix 486DLC
  5. ;    updated 04/19/94 to better test for 586/Pentium chip
  6. ;       updated 06/09/94 for data from Intel 486SX Data Book
  7.  
  8. DOSSEG
  9. .MODEL MEDIUM
  10. .CODE
  11. .8086    ; necessary for use w/ 16 bit segments
  12. ;.486P  ; can't use this if want to use w/ 16 bit compilers or 16 bit
  13. ;       ; chips, 
  14.  
  15.     PUBLIC CHIPTYPE
  16.  
  17. ;=======================================================================
  18. ;   Copyright (C) Copr. 1993, 1994 by Sidney J. Kelly
  19. ;           All Rights Reserved.
  20. ;           Sidney J. Kelly
  21. ;           150 Woodhaven Drive
  22. ;           Pittsburgh, PA 15228
  23. ;           home phone 412-561-0950 (7pm to 9:30pm EST)
  24. ;=======================================================================
  25. ;;«RM82»«TS8,16,24,32,40»
  26.  
  27. ;=======================================================================
  28. ; DECLARE FUNCTION CHIPTYPE% ()
  29. ; Returns:
  30. ;     586 if Pentium(tm) in real mode           (not tested)
  31. ;    -586 if Pentium(tm) in protected mode      (not tested)
  32. ;     486 if 80486 (DX or SX) in real mode      (tested SX & DX)
  33. ;     (can be a CX 486D or CX 486S, CX 486DX2, or CX 486DLC, or AMD)
  34. ;        (Can't yet distinguish between Intel 486SX and a CX 486S)
  35. ;    -486 if 80486 (DX or SX) in protected mode (tested SX & DX)
  36. ;     (can be a CX 486D or CX 486S, CX 486DX2, or CX 486DLC, or AMD)
  37. ;     480 if IBM 486SLC in real mode  (tested)
  38. ;    -480 if IBM 486SLC in protected mode  (tested)
  39. ;       CYRIX 486/INTEL 486 clear the reserved bits in the machine status
  40. ;       word (CR0), while IBM 486SCL2/50, 386DX and 386SX do not.
  41. ;       Tested w/ an IBM 486SLC2/66 with a math coprocessor and
  42. ;       an IBM 486SLC2/50 without a math coprocessor.
  43. ;       The SLC2 uses a 16 bit external bus chip (386SX style), while
  44. ;       the Intel 486DX/SX uses a 32 bit bus.  Unlike the Intel chip,
  45. ;       the SLC has an 16K internal cache versus an 8k internal cache
  46. ;       for the Intel 486DX.  A 33 MHz IIT 387SX NDP (with an IBM SLC2/66)
  47. ;       is as fast as the 387 that is part of a 486DX 25mhz.
  48. ;     479 if Cyrix 486DLC in real mode
  49. ;     386 if 80386DX in real mode               (tested)
  50. ;     376 if 80386SX in real mode (newer chips only) (tested)
  51. ;    -386 if 80386DX or 80386SX in protected mode (because shouldn't check
  52. ;         for 386SX in protected mode)       (tested)
  53. ;     286 if 80286                              (tested)
  54. ;     186 if 80186            (normally only seen on Tandy 2000)
  55. ;     188 if 80188            (very rare) (not tested)
  56. ;      32 if NEC 20            (equivalent to 8088)
  57. ;      30 if NEC 30            (equivalent to 8086)
  58. ;      88 if 8088            (tested) (standard PC/XT)
  59. ;      86 if 8086            (AT&T 6300, COMPAQ Systempro, WANG)
  60. ;
  61. ; CYRIX 486 chips
  62. ;         486DLC 1kb on chip cache, no integrated math, 386DX pin compatible
  63. ;      486DLU 1kb on chip cache, no integrated math, is a 286 upgrade chip
  64. ;     486DX pin compatible chips (same as Intel chips)
  65. ;         486D   2kb on chip cache, integrated coprocessor,
  66. ;         486S   2kb on chip cache, no coprocessor
  67. ;     486DX2 pin compatible now with an 8K cache (not tested)
  68. ;
  69. ; Registers:
  70. ;     Destroys: EAX and ECX on 80386+
  71. ;               AX,BX,CX and DX on all chips
  72. ;
  73. ; Tested with Windows 3.1, extended mode, NO UAE's!!
  74. ; Tested with EMM386.EXE and 386MAX version 7.0
  75. ;
  76. ; Not tested with QEMM or OS/2
  77. ;
  78. ; This code is based on code from Intel's "i486 Programmers Reference Manual"
  79. ; cpuid32.asm  - Per file
  80. ;  "This program has been developed by Intel Corporation.  You have
  81. ;   Intel's permission to incorporate this source code into your
  82. ;   product royalty free."
  83. ;  as modified by Wayne A. King, [CIS: 70022,2700] 5/24/93 for use w/ 
  84. ;  MASM 5.1, to correct bugs w/ real mode processors and 32 bit instructions
  85. ;=======================================================================
  86.  
  87. OPCODE_32   MACRO
  88.     DB     66h        ; opcode for 32 bit addressing
  89. ENDM                ; used on 80386/80486/Pentium
  90. CPUID MACRO        ; Hardcoded opcode for CPUID instruction
  91.    DB      0Fh,0A2h     ; only works on Pentium(tm)
  92. ENDM            ;  will not work on 80386/80486 (illegal op code)
  93.  
  94. EVEN
  95. Old_Value   DW  0               ; hold chiptype from last call
  96.  
  97.  
  98. ; Please do not remove
  99. Copyright       DB    13,10,'Copyright Copr. (C) 1990, 1991, 1994 Sidney J. Kelly',13,10
  100. Copyright1      DB    'All Rights Reserved',13,10,26
  101.  
  102. EVEN
  103. CHIPTYPE PROC FAR
  104.     Push    BP              ; preserve BP
  105.     Mov     BP,SP           ; save SP
  106.     Push    SI              ; save SI
  107.     Push    DI        ; save DI
  108.     PushF                   ; save flags
  109.     Mov     AX,CS:[Old_Value]  ; have we done this before?
  110.     Or      AX,AX           ; is AX = 0
  111.     JZ      @f              ; yes, so find chip type
  112.     Jmp     Finis_Fast      ; else, got value, it can't change. so quit
  113. ;-----------------------------------------------------------------------
  114. ; To test for real mode chips, test the value of SP after it is placed on the
  115. ; stack.  The real mode chips increment SP before pushing it on the stack,
  116. ; 80286+ CPU's increment SP _after_ pushing it on the stack.
  117. ;-----------------------------------------------------------------------
  118. @@:
  119.     Push    SP
  120.     Pop    AX
  121.     CMP    SP,AX        ; if real mode, these values will differ
  122.     JZ    Test_Newer    ; no, same value test newer chips
  123. ;-----------------------------------------------------------------------
  124. ; Test for 8086, 8088, 80188, 80186, NEC v20, NEC v30
  125. ;-----------------------------------------------------------------------
  126. Test_Real:            ; Test real mode chips
  127.     Mov    DX,188        ; assume 80188 chip
  128.     Mov    AX,-1        ; put 0FFFFh in AX
  129.     Mov    CL,33        ; prepare to shift AX right 33 times
  130.     SHR    AX,CL        ; 8018x+ chips wont allow this
  131.     JNZ    Test_Queue    ; if AX <> 0 then have 80188/80186
  132.     Mov    DX,32        ; assume NEC chip
  133.     STI            ; test for NEC
  134.     Mov    CX,-1        ; loop 64kb times
  135.     Xor    SI,SI        ; load a 0 into SI
  136.     Rep     Lods Byte Ptr ES:[SI]   ; only  NEC can REP w/ segment
  137.     ; override.   NEC also sets ZF if multiply using a 0 number
  138.     ; Intel chips couldn't use Rep w/ segment override until
  139.     ; 80386+ chip
  140.     JCXZ    Test_Queue    ; if CX = 0 then a NEC
  141.     Mov    DX,88        ; else, report 8088, not a NEC
  142. ;----------------
  143. ; Queue length is 2 bytes on 8088, 4 bytes on 8086, 6 bytes on 80286
  144. ; 16 bytes on 386, 32 bytes on 486, and 128 bytes on the Pentium
  145. ; per Abrash, PC Techniques (March/April 1994), Intel 486SX Data Book, p 188
  146. ; Abrash, "Zen of Assembly Language" (Scott Foresman 1990),
  147. ; ISBN 0-673-38602-3, page 701
  148. ; However, Pentium invalidates its queue if it determines that
  149. ; a write as occurred to queue stream, so can't use this routine
  150. ; to determine the length of queue on a Pentium
  151. ;----------------
  152. Test_Queue:
  153.     Push    CS        ; point ES to CS
  154.     Pop    ES
  155.     STD            ; move direction down
  156.     Mov    AL,0FBh        ; load op code for STI in AL
  157.     Mov    CX,3        ; load 3 bytes
  158.     Xor    BX,BX        ; start counter (BX) w/ a 0
  159.     CALL    Calc_Q_Offset    ; flush queue, and calc offset
  160. Jmp_Back_Entry:
  161.     CLI
  162.     Rep    STOSB        ; determine length of queue
  163.     CLD            ; reset direction flag
  164.     NOP
  165.     NOP
  166.     NOP
  167.     Inc    BX        ; test if BX changed?
  168.     NOP
  169.     STI            ; allow flags again
  170.     Or    BX,BX        ; if BX still 0
  171.     JZ    @f        ; then quit
  172.     Sub    DX,2        ; note have longer queue (8086/80186/V30)
  173. @@:
  174.     Jmp     Finis           ; quit
  175. Calc_Q_Offset:
  176.     Pop    DI        ; get offset address into DI
  177.     Add     DI,9            ; add 9
  178.     Jmp     Short Jmp_Back_Entry    ; jump back
  179. ;-----------------------------------------------------------------------
  180. ;   Test for 80386 and above, by checking to see if Bit 14
  181. ;   On the 286 chip, none of the flags from 12 to 15 can be set in real
  182. ; mode.  All bits fixed to 0
  183. ;   On a 386+ bit 15 is permanently set to 0,  bit 14 (NT - Nested Task) 
  184. ; can be toggled no matter what the current protection mode.  
  185. ; Bits 12-13 on 80386+ can be toggled if in real mode or if current protection
  186. ; mode is 0 (CPL=0 or ring0)
  187. ;-----------------------------------------------------------------------
  188. Test_Newer:            ; test for 80386+
  189.     Mov    DX,286        ; assume have 286
  190.     CLI            ; prevent interruptions
  191.     PushF            ; save flags
  192.     Pop    AX        ; copy to AX
  193.     Or    AX,4000h    ; set bit 14
  194.     Push    AX        ; save AX
  195.     PopF            ; pop into flag register
  196.     PushF            ; push new flags
  197.     Pop    AX        ; get into AX
  198.     STI            ; allow interruptions again
  199.     TEST    AX,4000h    ; is bit 14 clear?
  200.     Jnz     TEST_4_486      ; if set have 80386+ chip
  201. ;--------------------------------
  202. ; Windows enhanced mode has a bug in POPF instruction emulation
  203. ; We test machine to see if in protected mode.
  204. ; This routine will guess wrong if using 286 extended mode software
  205. ;--------------------------------
  206.     ;SMSW    AX        ; test if protected mode set
  207.     DB    0Fh,01h,0E0h    ; get machine status into AX
  208.     Test    AX,0001b    ; are we in protected mode?
  209.     Jnz    TEST_4_486    ; yes, more likely a 386+ than a 286
  210.     Jmp     Finis           ; quit, report back as a 80286
  211. ;=====================================================================
  212. ;   Cpu type is an 80386 or 80486
  213. ;   This code should not bomb if the machine is in protected mode.
  214. ;
  215. ; The 486 has defined Bit 18 (AF) in EFLAGS which will enable alignment
  216. ; faults.  The 386 does not have this.  This test will set the bit
  217. ; to determine if the processor type is a 486.  First the stack must
  218. ; be aligned so that the fault does not occur.
  219. ;
  220. ; Source: TYPE.ASM in PCEO converted by Francis Leung based on help from
  221. ; Al Kinney, the sysop of Intel's PCEO forum.
  222. ; and PCMAG, Feb 26, 1991 V10N4, p. 416 (Duncan states the information
  223. ; is derived from Intel code).  Another similar version was modified by
  224. ; Ernest Vogelsinger, (CIS ID 100015,551.), again based on Intel code.
  225. ;
  226. ; The "Official Intel Method" was published in "Intel486 SX Microprocessor
  227. ; Intel487 SX Math CoProcessor Data Book" (Intel 1991)
  228. ; ISBN 1-55512-158-6, Appendix B, page B-1.  The Intel code will work 
  229. ;  on a 16 bit compiler.
  230. ; NOTE:
  231. ; This section will falsely report cpu as a 486 if a 386 is single stepped in
  232. ; CODEVIEW and report cpu as a 386 if a 486 is single stepped in CODEVIEW
  233. ;=====================================================================
  234. TEST_4_486:
  235.     Mov    DX,386        ; assume have 386
  236.     Mov     BX,SP           ; save original SP in BX
  237.     CLI            ; prevent interrupts
  238.     And     SP, NOT 3       ; align stack, clear AC flag on 486
  239.      OPCODE_32
  240.     PushF            ; PushFD
  241.      OPCODE_32        ; copy flags into EAX
  242.     Pop    AX        ; Pop EAX
  243.      OPCODE_32
  244.     Mov    CX,AX        ; copy EAX (flags) to ECX
  245. ; ECX has a copy of original flags
  246. ;       Xor     EAX,040000h     ; flip bit 18
  247.      DB 66h,35h,00,00,04,00    ; Xor  EAX,40000h   ; toggle bit 18
  248.      OPCODE_32
  249.     Push    AX        ; Push EAX (flags)
  250.      OPCODE_32        ; get it back
  251.     PopF            ; PopFD
  252.      OPCODE_32        ; save it again
  253.     PushF            ; PushFD
  254.      OPCODE_32        ; get it in EAX
  255.     Pop    AX        ; Pop  EAX
  256.     STI            ; allow interrupts again
  257.      OPCODE_32        ; eliminate all but bit 18, changes flags too
  258.     Xor    AX,CX        ; Xor     EAX,ECX
  259.     Mov     SP,BX           ; restore SP
  260.     JNZ     Test_486_Type    ; have 486/586
  261.     Jmp     Short Test_386_Type   ; have 80386 if no bit set
  262. Test_486_Type:
  263.     CLI            ; halt interrupts
  264.     And     SP, NOT 3       ; else, align stack again to avoid faults
  265.     Mov     DX,486          ; and report have 486
  266.      OPCODE_32        ; restore original flags
  267.     Push    CX        ; Push ECX
  268.      OPCODE_32        ; get flags back
  269.     PopF            ; PopFD
  270.     Mov     SP,BX           ; restore SP again
  271.     STI            ; allow interrupts again
  272.     ;------------------------------------------------------------------
  273.     ; SMSW reads lower 16 bits of CR0 on an 80386+.  However, it
  274.     ;  does not trigger a fault in protected mode as would reading CR0.
  275.     ;------------------------------------------------------------------
  276. ;    SMSW    AX        ; test if protected mode set
  277.      DB    0Fh,01h,0E0h    ; get machine status into AX
  278.     ;------------------------------------------------------------------
  279.     ; Test for IBM 486SLC chips based on difference of treatment of
  280.     ; reserved bits in CR0 / machine status register
  281.     ;------------------------------------------------------------------
  282.     Or      AH,AH           ; is AH = 0
  283.     Jz      Test_4_DLC      ; YES, it is not an IBM SLC
  284.     Mov     DX,480          ; else report IBM SLC
  285.     Jmp     Short TY_486
  286. Test_4_DLC:
  287.     TEST    AX,0001b    ; are we in protected mode
  288.     Jnz     TY_486          ; yes, can't test for DLC safely
  289.     Call    Test_DLC    ; test for DLC
  290.     Jmp    Short    @f    ; continue on
  291. TY_486:
  292.     TEST    AX,0001b        ; is bit 0 set?
  293.     JZ      @f              ; no, not in protected mode
  294.     Neg    DX        ; else, report 486 in protected mode
  295. @@:
  296.     ;------------------------------------------------------------------
  297.     ; Determine if CPU supports CPUID instruction by seeing if
  298.     ; can set and clear ID flag (Bit 21) in EFLAGS.
  299.     ; Pentium uses this flag to say that CPUID is supported
  300.     ; Can't use this test on revision A of 386DX chips, so must make
  301.     ; sure have a 486+ first before we test.
  302.     ; On a 486 chip, this bit is undefined (0), per Intel 486SX Data Book
  303.     ; ?The bit may be used by 487SX to tell 486SX to shut
  304.     ; down because 487SX is active  (undocumented)?  However, bit is
  305.     ; not used on a 486DX
  306.     ;------------------------------------------------------------------
  307.     CLI            ; disable interrupts
  308.      OPCODE_32
  309.         Mov     AX,CX        ; get original EFLAGS
  310. ;       Xor     EAX,200000h     ; flip bit 21
  311.     DB   66h,35h,00,00,20h,00    ; Xor  EAX,200000h   ; toggle bit 21
  312.      OPCODE_32
  313.         Push    AX        ; save new EFLAGS value on stack
  314.      OPCODE_32
  315.         PopF            ; replace current EFLAGS value
  316.      OPCODE_32
  317.         PushF            ; get new EFLAGS
  318.      OPCODE_32
  319.         Pop     AX        ; store new EFLAGS in EAX
  320.      OPCODE_32
  321.     STI            ; allow interrupts again
  322.         Xor     AX,CX        ; can't toggle ID bit,
  323.     Jne     Get_Pentium_Info  ; may have Pentium
  324.     Jmp     Short Finis       ; have plain old 486
  325. Get_Pentium_Info:
  326. ;    Mov    EAX,1        ; get family info function
  327.     ; returns in AL a value of 5 if a Pentium
  328.     DB  66h,0B8h,01,00,00,00
  329.         CPUID            ; macro for CPUID instruction
  330.     ; if EAX is set to 0 before calling CPUID then
  331.     ; then a text string is returned in EBX,ECX and EDX
  332. ;    And    EAX,0F00h    ; find family info
  333.     DB  66h,25h,00,0Fh,00,00
  334. ;    Shr    EAX,8
  335.     DB  66h,0C1h,0E8h,08
  336.     Mov    DX,586        ; assume Pentium
  337.     Cmp    AL,5
  338.     Je    F_Status    ; have a Pentium
  339.     Mov    DX,486        ; else, do not have Pentium
  340. F_Status:
  341. ;    SMSW    AX        ; test if protected mode set
  342.      DB    0Fh,01h,0E0h    ; get machine status
  343.     TEST    AX,0001b    ; is bit 0 set?
  344.     JZ      @f              ; no, not in protected mode
  345.     Neg    DX        ; else, report chip in protected mode
  346. @@:
  347.     Jmp     Short Finis     ; quit
  348. Test_386_Type:
  349.     ;------------------------------------------------------------------
  350.     ; SMSW reads lower 16 bits of CR0 on an 80386+.  However, it
  351.     ;  does not trigger a fault in protected mode as would reading CR0.
  352.     ;------------------------------------------------------------------
  353. ;    SMSW    AX        ; test if protected mode set
  354.      DB    0Fh,01h,0E0h    ; get machine status
  355.     TEST    AX,0001b    ; is bit 0 set?
  356.     JNZ    Prot_Mode    ; yes in protected mode
  357.     ;------------------------------------------------------------------
  358.     ; Check for 386SX by trying to set the co-processor type bit in CR0,
  359.     ;  the Extension Type (ET) (bit 4) bit.
  360.     ; On the 386DX this bit is defined, on the newer 386SX it is not.
  361.     ; On a 486 chip, the bit is permanently set to 1, per
  362.     ; Intel 486SX Data Book, page 28
  363.      ;
  364.     ; Get current CR0 and save in ECX.
  365.     ;
  366.     ; Don't run this section in protected mode!!
  367.     ; NOTE this will trigger a protection interrupt and thus is
  368.     ; not usable under Windows 3.0 or QEMM-386.
  369.     ;
  370.     ; 486SX chip uses similar bit in EFLAGS, ID flag (bit 21), for
  371.     ; information whether a co-processor is installed 
  372.     ;------------------------------------------------------------------
  373. ;    Mov     EAX, CR0
  374.      DB    0Fh,20h,0C0h    ; Mov   EAX, CR0
  375. ;    Mov     ECX, EAX
  376.      OPCODE_32
  377.     Mov    CX,AX        ; Mov   ECX,EAX
  378.     ;------------------------------------------------------------------
  379. COMMENT      *|
  380.         ┌──┬──┬──┬─┬─┬─┬─┬─┬─┐      CR0
  381.         │31│30│ ▓│5│4│3│2│1│0│  Machine Status Word (80386/80486)
  382.         └┬─┴┬─┴┬─┴┬┴┬┴┬┴┬┴┬┴┬┘  (undefined bits are usually 1)
  383.          │  │  |  │ │ │ │ │ └──── Protection Enable (PE) (bit 0)
  384.          │  │  |  │ │ │ │ └───── Monitor Coprocessor (MP)(bit 1)
  385.          │  │  |  │ │ │ └────── Emulation (EM)           (bit 2)
  386.          │  │  |  │ │ └─────── Task Switched (TS)        (bit 3)
  387.          │  │  |  │ └──────── Extension Type (ET)        (bit 4)
  388.          │  │  |  │       (386 chip only, 486 chip sets bit to 1)
  389.          │  │  |  └─────── Numerics Exception (NE)       (bit 5)
  390.          │  │  |           (Should be 0 for 486DX+)
  391.          │  │  └----------─ Reserved                    (bits 6-29)
  392.          │  │  (On an Cyrix 486D/486S and Intel 486SX, undefined bits
  393.          │  │    are 0 ---
  394.          │  │   But the  undefined bits on IBM 486SLC2 and 386DX, 386SX
  395.          │  │   are 1 when read using SMSW)
  396.          │  └─────────── Internal Cache disable (CD) - 486 chip only
  397.          └───────────── Paging (PG)                  (bit 31)
  398.  
  399.          On a 386 chip, the MSW is the lower 16 bits of CR0
  400.  
  401.          PE  Protection Enable, CPU in protected mode or virtual 8086 mode
  402.         if bit is set. (80286 uses same bit in MSW)
  403.          MP  Monitor Coprocessor, controls treatment of the FWAIT
  404.              instruction.  If TS = 1 then coprocessor not available
  405.          trap will be executed. (80286 uses same bit in MSW)
  406.          EM  Emulation, indicates whether coprocessor functions
  407.              are emulated .  If EM = 0 then all 80x87 opcodes executed
  408.          on a real 80x87. (80286 chip uses this bit in MSW)
  409.          TS  Task Switched, used by coprocessor
  410.          (80286 chip uses this bit in MSW, balance of bits are not used)
  411.          ET  Extension Type, indicates whether 80837 or 80287 chip in use.
  412.          Newer 80386SX chips do not allow this bit to be changed
  413.          Bit is set to 1 on a 486 chip
  414.      CD  Cache disable bit (486 only)
  415.          PG  Paging, indicates whether the processor uses page
  416.              tables to translate linear addresses to physical
  417.          addresses.  V8086 mode normally does not, WINDOWS 386 mode does.
  418.  
  419. Typical status from MSW:
  420.     EMM386.EXE     0001b or PE = 1 (Virtual 386 mode)
  421.                Mathchip emulation, protection enable
  422.     EM87.COM       0100b  or EM = 1  (real mode on 386SX)
  423.                Mathchip emulation.
  424.  
  425.          Virtual 8086 mode requires PE to be set as well as bit 17 of EFLAGS
  426.          register.  
  427.  
  428.   See,  Murray, "80386/80286 Assembly Language Programming"
  429.                 (Osborne 1986) (ISBN 0-07-881217-8), p 55-65
  430. COMMEND        |*
  431.     ;---------------------
  432.     ; Flip the ET bit and save it back in CR0.
  433.     ;---------------------
  434. ;    Xor     EAX,10H            ; flip bit 4
  435.      DB    66h,35h,10h,00,00,00    ; Xor EAX,10H
  436. ;    Mov     CR0, EAX
  437.      DB    0Fh,22h,0C0h    ; Mov CR0,EAX
  438.     ;---------------------
  439.     ; Get CR0 to test the ET bit.  Restore CR0 to original value.
  440.     ;---------------------
  441. ;    Mov     EAX, CR0
  442.      DB    0Fh,20h,0C0h    ; Mov     EAX, CR0
  443. ;    Mov     CR0, ECX
  444.      DB    0Fh,22h,0C1h    ; Mov     CR0,ECX
  445.     ;------------------------------------------------------------------
  446.     ; If the ET bit is different from what it was to begin with, then we
  447.     ; have a 386DX (NOTE: the first stepping of the 386SX supported the
  448.     ; 287, and therefore used this bit.  That means that this test will
  449.     ; identify an early 386SX as 386DX).  All AMD's are second stepping
  450.     ;------------------------------------------------------------------
  451.      OPCODE_32
  452.     Xor    AX,CX        ; Xor     EAX,ECX
  453.     Jnz     Finis
  454.     Sub    DX,10        ; report back have a 80386SX
  455.     Jmp     Short Finis
  456. Prot_Mode:
  457.     NEG    DX        ; report in protected mode
  458. Finis:
  459.     Mov     AX,DX           ; get return code in AX
  460.     Mov     CS:[Old_Value],AX ; save it
  461. Finis_Fast:
  462.     Popf                    ; restore flags
  463.     STI            ; make sure interrupts allowed
  464.     Pop    DI        ; restore DI
  465.     Pop    SI        ; restore SI
  466.     Mov    SP,BP        ; restore SP
  467.     Pop    BP        ; restore BP
  468.     Ret
  469. CHIPTYPE ENDP
  470.  
  471. ;=======================================================================
  472. ; Test for Cyrix/TI/IBM  DLC/SLC
  473. ;        If cannot toggle bit 5 of CR0 then have
  474. ;      a Cyrix 486 SLC/DLC and ZR set
  475. ;
  476. ;       Bit 5 is the Numerics Exception Bit.  It should be 1 on an
  477. ;       486SX and 0 on a 486DX,487SX
  478. ; Note:
  479. ;    Test should only be performed in real mode because may trigger
  480. ;       an error under a memory manager such as Windows 3.0
  481. ;=======================================================================
  482.  
  483. EVEN
  484. Test_DLC PROC NEAR
  485.      OPCODE_32
  486.     Push    BX    ; Push      EBX
  487.     ; Mov    EBX,CR0
  488.     DB 0Fh,20h,0C3h
  489.      OPCODE_32
  490.     Mov    AX,BX    ; Mov       EAX,EBX
  491.     ; Xor    EAX,+20h
  492.     DB 66h,83h,0F0h,20h   ; see if can toggle bit 5 of CR0
  493.     ; Mov    CR0,EAX
  494.     DB 0Fh,22h,0C0h
  495.     ; Mov    EAX,CR0
  496.     DB 0Fh,20h,0C0h
  497.     ; Mov    CR0,EBX
  498.     DB 0Fh,22h,0C3h
  499.      OPCODE_32
  500.     Cmp    AX,BX    ; Cmp       EAX,EBX
  501.      OPCODE_32
  502.     Pop    BX      ; Pop       EBX
  503.     Jnz    @f        ; not a DLU
  504.     Mov    DX,479
  505. @@:
  506.     Ret
  507. Test_DLC ENDP
  508. END
  509.  
  510.  
  511.                  CPU Characteristics / Determination
  512.  
  513. 1). Early vs. Later chips
  514.     a). 80286, 80386.  Earlier CPU's decremented SP before a PUSH SP
  515.        but 286+ pushes the value first, then decrements SP or
  516.     b). 8088,8086,80188,80186,NEC v20,NEC v30  Flag register bits 12
  517.        through 15 cannot be cleared
  518.  
  519. 2). 80286 vs. 80386 chip
  520.     a). 80286 allows setting of bit 15 of the flags register
  521.     b). 80386 allows setting of bits 12 through 14 of flags register
  522.  
  523. 3). 8088 and 8086 vs. Modern chips
  524.     a). 80188, 80186, NEC v20, NEC v30 will shift left or right
  525.     using only lower 5 bits of CL.  If CL = 32, the shift will not
  526.     occur
  527.  
  528.     b). 8088, 8086 will shift left or right using all 8 bits of CL
  529.        if CL = 33, register is guaranteed to be cleared
  530.  
  531. 4). Intel 8088,8086 vs. NEC v20/v30
  532.     a). 8088,8086 nonzero multiplication result clears zero flag
  533.  
  534.      b). V20,V30   nonzero multiplication result does not clear
  535.     zero  flag, set ZF before multiply, and test after, if it's
  536.         still set, then it's a V20, V30
  537.  
  538. 5). Determine bus width
  539.     8088 vs. 8086,    80188 vs. 80186,  NEC  v20  vs. v30
  540.  
  541.     a). 8088,80188,V20  two byte prefetch queue
  542.  
  543.      b). 8086,80186,V30  four byte prefetch queue
  544.  
  545. Source:  "Chips In Transition", PC Tech Journal  (April 1986)
  546.  
  547. 6). 80386 vs. 80486
  548.     80486 in Flags register has an alignment bit for stack faults
  549.     80386 does not
  550.  
  551. 7). 80486SX vs. 80486DX
  552.     80486DX has a built-in 80387, 80486SX does not
  553.  
  554. 8)  80386DX vs. 80386SX
  555.     in MSW bit 4 (ET bit) toggles on old 386SX and all 80386DX
  556.     does not toggle on newer 80386SX.  Should only test in real mode.
  557.  
  558. ;=======================================================================
  559.  The following instructions are privileged 386 instructions.  Execution
  560.  of  any of these instructions in protected mode will trigger a 386
  561.  fault interrupt.  Early versions of 386 memory managers (QEMM/Windows 3.0)
  562.  did not properly handle the error and would crash (Windows would send a UAE). 
  563.    PC Mag (February 26, 1991) page 415, V10N4P415
  564.  
  565.  More modern memory managers permit a change to CR0 and have that change
  566.  stick (e.g. 386MAX Version 7.0).
  567.  
  568.  However, Windows 3.1, Enhanced mode does permit access to CR0 without
  569.  an error because it resets CR0 to its orgininal state after the 
  570.  DOS program changes it.  Windows 3.0 did not permit such access without
  571.  triggering an "UAE."
  572.  
  573.     CLTS        Clear Task Switched Flag
  574.     HLT        Halt CPU until receives co-processor interrupt
  575.     LGDT        Load Global Descriptor Table Register
  576.     LIDT        Load Interrupt Descriptor Table Register
  577.     LLDT        Load Local Descriptor Table Register
  578.     LMSW        Load Machine status word
  579.         LSL        Load Segment limit
  580.     LTR        Load Task register
  581.     Mov    CRn,reg     Move data to control register
  582.     Mov    reg,CRn     Move date from control register
  583.     Mov    DRn,reg     Move data to debug register
  584.         Mov    reg,DRn  Move data from debug register
  585.     Mov    reg,TRn  Move data from test register
  586.     Mov    TRn,reg     Move data to test register
  587.  See, also, Murray, "80386/80286 Assembly Language Programming"
  588.             (Osborne 1986) (ISBN 0-07-881217-8), p 140
  589. ;=======================================================================
  590.  
  591.