home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / source / 80486.asm < prev    next >
Assembly Source File  |  1989-05-29  |  7KB  |  166 lines

  1. ;-----------------------------------------------------------------------------
  2. ; CPU_Type determines the CPU type in the system.
  3. ;-----------------------------------------------------------------------------
  4. ; Written by:
  5. ;   Robert Collins
  6. ;   3361 Keys Lane
  7. ;   Anaheim, CA  92804
  8. ;-----------------------------------------------------------------------------
  9. ; Input:   None
  10. ; Output:  AX = CPU type
  11. ;           0 = 8086/8088
  12. ;           1 = 80186/80188
  13. ;           2 = 80286
  14. ;           3 = 80386
  15. ;           4 = 80486
  16. ;        FFFF = Unknown CPU type
  17. ;-----------------------------------------------------------------------------
  18.  
  19. .radix 16                       ; anybody that programs in base 10 is a wimp!
  20. .386P                           ; MASM 5.1 directive
  21.  
  22. ;-----------------------------------------------------------------------------
  23. ; PUBLIC statements here
  24. ;-----------------------------------------------------------------------------
  25.         Public  CPU_Type
  26.  
  27. ;-----------------------------------------------------------------------------
  28. ; Local variable definitions
  29. ;-----------------------------------------------------------------------------
  30.         INT6    equ     [bp-4]
  31.  
  32. ;-----------------------------------------------------------------------------
  33. ; Interrupt vector segment
  34. ;-----------------------------------------------------------------------------
  35. ABS0    segment use16 at 0
  36.  
  37.         org 6*4
  38. Orig_INT6       dd      ?
  39.  
  40. ABS0    ends
  41.  
  42.  
  43. ;-----------------------------------------------------------------------------
  44. ; 80486 instruction macro -- because MASM 5.1 doesn't support the 80486!
  45. ;-----------------------------------------------------------------------------
  46. XADD    macro
  47.         db      0fh,0C0h,0D2h           ; 80486 instruction macro
  48. ENDM
  49.  
  50.  
  51. cseg    segment para    use16 public 'code'
  52.         assume  cs:cseg
  53.  
  54. CPU_Type        proc    near
  55. ;-----------------------------------------------------------------------------
  56. ; Determine the CPU type by testing for differences in the CPU in the system.
  57. ;-----------------------------------------------------------------------------
  58. ; To test for the 8086/8088, test the value of SP after it is placed on the
  59. ; stack.  The 8086/8088 increments this value before pushing it on the stack,
  60. ; all other CPU's increment SP after pushing it on the stack.
  61. ;-----------------------------------------------------------------------------
  62.         xor     ax,ax                   ; clear CPU type return register
  63.         push    sp                      ; save SP on stack to look at
  64.         pop     bx                      ; get SP saved on stack
  65.         cmp     bx,sp                   ; if 8086/8088, these values will differ
  66.         jnz     CPU_8086_exit           ; yep
  67. ;-----------------------------------------------------------------------------
  68. ; When we get here, we know that we aren't a 8086/8088.  And since all
  69. ; subsequent processors will trap invalid opcodes via INT6, we will determine
  70. ; which CPU we are by trapping an invalid opcode.
  71. ;   We are an 80486 if:  XADD   DX,DX   executes correctly
  72. ;             80386 if:  MOV    EDX,CR0 executes correctly
  73. ;             80286 if:  SMSW   DX      executes correctly
  74. ;             80186 if:  SHL    DX,5    executes correctly
  75. ;-----------------------------------------------------------------------------
  76. ; Setup INT6 handler
  77. ;-----------------------------------------------------------------------------
  78.         enter   4,0                     ; create stack frame
  79.         mov     word ptr INT6,offset INT6_handler
  80.         mov     INT6+2,cs
  81.         call    set_INT6_vector         ; set pointer to our INT6 handler
  82.         mov     ax,4                    ; initialize CPU flag=4 (80486)
  83.         xor     cx,cx                   ; initialize semaphore
  84.  
  85. ;-----------------------------------------------------------------------------
  86. ; Now, try and determine which CPU we are by executing invalid opcodes.
  87. ; The instructions I chose to invoke invalid opcodes, are themselves rather
  88. ; benign.  In each case, the chosen instruction modifies the DX register,
  89. ; and nothing else.  No system parameters are changed, e.g. protected mode,
  90. ; or other CPU dependant features.
  91. ;-----------------------------------------------------------------------------
  92. ; The 80486 instruction 'XADD' xchanges the registers, then adds them.
  93. ; The exact syntax for a '486 compiler would be:  XADD  DX,DX.
  94. ;-----------------------------------------------------------------------------
  95.         XADD   ;DX,DX                   ; 80486
  96.         jcxz    CPU_exit
  97.         dec     ax                      ; set 80386 semaphore
  98.         inc     cx                      ; CX=0
  99.  
  100. ;-----------------------------------------------------------------------------
  101. ; For a description on the effects of the following instructions, look in
  102. ; the Intel Programmers Reference Manual's for the 80186, 80286, or 80386.
  103. ;-----------------------------------------------------------------------------
  104.         mov     edx,cr0                 ; 80386
  105.         jcxz    CPU_exit
  106.         dec     ax                      ; set 80286 semaphore
  107.         inc     cx                      ; CX=0
  108.  
  109.         smsw    dx                      ; 80286
  110.         jcxz    CPU_exit
  111.         dec     ax                      ; set 80186 semaphore
  112.         inc     cx                      ; CX=0
  113.  
  114.         shl     dx,5                    ; 80186/80188
  115.         jcxz    CPU_exit
  116.         dec     ax                      ; set UNKNOWN_CPU semaphore
  117.  
  118. CPU_exit:
  119.         call    set_INT6_vector
  120.         leave
  121.  
  122. CPU_8086_exit:
  123.         ret
  124.  
  125.  
  126. ;-----------------------------------------------------------------------------
  127. ; Set the INT6 vector by exchanging it with the one currently on the stack.
  128. ;-----------------------------------------------------------------------------
  129. set_INT6_vector:
  130.         push    ds
  131.         push    ABS0                    ; save interrupt vector segment
  132.         pop     ds                      ; make DS=INT vector segment
  133.         mov     dx,word ptr ds:Orig_INT6;       ; get offset if INT6 handler
  134.         xchg    INT6,dx                 ; set new INT6 offset
  135.         mov     word ptr ds:Orig_INT6,dx
  136.         mov     dx,word ptr ds:Orig_INT6+2      ; get segment of INT6 handler
  137.         xchg    INT6+2,dx               ; set new INT6 segment
  138.         mov     word ptr ds:Orig_INT6+2,dx
  139.         pop     ds                      ; restore segment register
  140.         ret                             ; split
  141.  
  142.  
  143. ;-----------------------------------------------------------------------------
  144. ; INT6 handler sets a semaphore (CX=FFFF) and adjusts the return address to
  145. ; point past the invalid opcode.
  146. ;-----------------------------------------------------------------------------
  147. INT6_handler:
  148.         enter   0,0                     ; create new stack frame
  149.         dec     cx                      ; make CX=FFFF
  150.         add     word ptr ss:[bp][2],3   ; point past invalid opcode
  151.         leave
  152.         iret
  153.  
  154. CPU_Type        endp
  155.  
  156. cseg    ends
  157.         end
  158.  
  159. -- 
  160. "Worship the Lord your God, and serve him only."  Mat. 4:10
  161. Robert Collins                 UUCP:  ucbvax!ucivax!icnvax!conexch!rob
  162. HOMENET:  (805) 523-3205       UUCP:  uunet!ccicpg!turnkey!conexch!rob
  163. WORKNET:  (805) 378-7901
  164.  
  165.  
  166.