home *** CD-ROM | disk | FTP | other *** search
/ BBS 1 / BBS#1.iso / for-dos / cpu116b2.ha / CPU_HL.ASM next >
Encoding:
Assembly Source File  |  1995-05-10  |  10.2 KB  |  712 lines

  1. ; -----------------------------------------------------------------------------
  2. ; CPU_HL.ASM   CPU Type detection routine for hi-level languages Version 1.16B2
  3. ;
  4. ; Too-Much-In-One-So-Don't-Get-Lost(tm) CPU/FPU feature detection library
  5. ;
  6. ; Copyright(c) 1992-95 by B-coolWare.  Written by Bobby Z.
  7. ; -----------------------------------------------------------------------------
  8. ; This is a port from CPU_TYPE.ASH - the assembler version of TMi0SDGL(tm)
  9. ; See file CPU_TYPE.ASH for extensive comments and all.
  10.  
  11.     INCLUDE    HEADER.ASH
  12.  
  13.     .DATA
  14.  
  15.     EXTRN FPUType:BYTE
  16.  
  17.     .CODE
  18.  
  19.     PUBLIC    CPU_Type
  20.     PUBLIC    checkEmu
  21. ;    PUBLIC    checkAMD
  22.  
  23. ; TP/BP:
  24. ; function CPU_Type : Word;
  25. ;
  26. ; C/C++:
  27. ; word CPU_Type(void);
  28. ;
  29. ; returns current CPU code (see CPUTYPE.PAS or CPUTYPE.H for details) and sets
  30. ; current FPU code in FPUType variable.
  31.  
  32. EF_AC        equ    00040000h    ; AC bit in EFLAGS register
  33. EF_ID        equ    00200000h    ; ID bit in EFLAGS register
  34. MSW_NE        equ    00000020h    ; NE bit in MSW register
  35.  
  36. cpuid        equ    <db 0Fh,0A2h>    ; new i486 & Pentium instruction
  37.  
  38. CPU_Type    proc
  39.     .8086
  40.     push    bx cx si
  41.     sub    bx,bx
  42.     push    sp
  43.     pop    ax
  44.     cmp    ax,sp
  45.     jnz    @@Ct_000
  46.     mov    ax,7000h
  47.     pushf
  48.     push    ax
  49.     popf
  50.     pushf
  51.     pop    ax
  52.     popf
  53.     mov    bl,6
  54.     and    ax,7000h
  55.     jz    @@Ct_200
  56.     inc    bx
  57.  
  58.     .386p
  59.     clr    si
  60.     mov    eax,cr0
  61.     mov    ecx,eax
  62.     xor    eax,10h
  63.     mov    cr0,eax
  64.     mov    eax,cr0
  65.     mov    cr0,ecx
  66.     xor    eax,ecx
  67.     jz    @@L100
  68.     inc    si
  69.  
  70. @@L100:
  71.  
  72.     .386
  73.  
  74.     mov    ax,sp
  75.     and    sp,0FFFCh
  76.     pushfd
  77.     pushfd
  78.     pop    edx
  79.     mov    ecx,edx
  80.     xor    edx,EF_AC
  81.     and    ecx,EF_AC
  82.     push    edx
  83.     popfd
  84.     pushfd
  85.     pop    edx
  86.     popfd
  87.     mov    sp,ax
  88.     and    edx,EF_AC
  89.     cmp    edx,ecx
  90.     jnz    @@486
  91.     or    si,si
  92.     jz    @@L1
  93.     inc    bx
  94.     jmp    @@L1
  95.  
  96. @@486:
  97.     mov    bx,0Ah
  98.     push    bx
  99.     mov    bx,100h
  100.     mov    ah,7Fh
  101.     cwd
  102.     sahf
  103.     div    bx
  104.     lahf
  105.     xor    al,ah
  106.     and    al,0D5h
  107.     pop    bx
  108.     jnz    @@586
  109.     inc    bx
  110.     inc    bx
  111.     or    si,si
  112.     jz    @@586
  113.     inc    bx
  114. @@586:
  115.  
  116.         pushfd
  117.     pop    eax
  118.     mov    ecx,eax
  119.     xor    eax,EF_ID
  120.     push    eax
  121.     popfd
  122.     pushfd
  123.     pop    eax
  124.     push    ecx
  125.     popfd
  126.     and    eax,EF_ID
  127.     and    ecx,EF_ID
  128.     cmp    eax,ecx
  129.     jz    @@486sdx
  130.     clr    eax
  131.     inc    al
  132.     push    bx
  133.     cpuid
  134.     pop    bx
  135.     and    ah,0Fh
  136.     cmp    ah,4
  137.     jb    @@386dx
  138.     je    @@486sdx2
  139.     cmp    bl,0Ch
  140.     jb    @@P5
  141.     cmp    bl,0Dh
  142.     ja    @@P5
  143.     mov    bl,0Fh
  144.     jmp    @@L1
  145. @@P5:
  146.     mov    bl,ah
  147.     cmp    bl,6
  148.     jz    @@P6
  149.     add    bl,9
  150.     jmp    @@L1
  151. @@P6:
  152.     mov    bl,18h
  153.     jmp    @@L1
  154. @@386dx:
  155.     call    checkIBMmsrs
  156.     jc    @@L1
  157.     mov    bx,7
  158.     or    si,si
  159.     jz    @@L1
  160.     inc    bx
  161.     jmp    @@L1
  162. @@486sdx2:
  163.     call    checkIBMmsrs2
  164.     jc    @@L1
  165.     mov    bl,0Ah
  166.     push    bx
  167.     clr    eax
  168.     inc    al
  169.     cpuid
  170.     pop    bx
  171.     and    ax,03F0h
  172.     cmp    ah,10h        ; type field set to 01 means this is Pentium Overdrive
  173.     jz    @@P24D
  174. @@noP24:
  175.     test    al,al
  176.     jnz    @@setNibble
  177.     inc    al
  178. @@setNibble:
  179.     or    bh,al
  180.     jmp    @@L1
  181. @@P24D:
  182.     mov    bl,10h
  183.     jmp    @@L1
  184.  
  185. @@486sdx:
  186.     .486p
  187.     call    isInOSZwei
  188.     jnz    @@L1
  189.     cmp    bl,0Dh
  190.     jae    @@L1
  191.     mov    eax,cr0
  192.     mov    ecx,eax
  193.     db    66h,83h,0E0h,0DFh
  194.     mov    cr0,eax
  195.     mov    eax,cr0
  196.     cmp    eax,ecx
  197.     jnz    @@486dx
  198.     or    eax,MSW_NE
  199.     mov    cr0,eax
  200.     mov    eax,cr0
  201.     cmp    eax,ecx
  202.     jnz    @@486dx
  203.     dec    bx
  204. @@486dx:
  205.     inc    bx
  206.     mov    eax,ecx
  207.     mov    cr0,eax
  208.  
  209. @@L1:
  210.     .286p
  211.     smsw    ax
  212.     and    al,1
  213.     or    bh,al
  214.     jmp    @@Ct_200
  215. @@Ct_000:
  216.     mov    bl,4
  217.     mov    cl,33
  218.     clr    ax
  219.     dec    ax
  220.     shl    ax,cl
  221.     jnz    @@Ct_100
  222.     mov    bl,2
  223.     clr    cx
  224.     dec    cx
  225.     db    0F3h,26h,0ACh
  226.     jcxz    @@Ct_100
  227.     clr    bx
  228. @@Ct_100:
  229.     clr    ax
  230.     call    Test_Buffer
  231.     jcxz    @@Ct_200
  232.     inc    bx
  233. @@Ct_200:
  234.     test    ah,0F0h
  235.     jz    @@checkFPU
  236.     test    dl,1
  237.     jz    @@checkFPU
  238.     mov    dl,10h
  239.     jmp    @@noCheck
  240. @@checkFPU:
  241.     call    FPU_Type
  242. @@noCheck:
  243.     call    checkWeitek
  244.     mov    FPUType,dl
  245.     mov    ax,bx
  246.     pop    si cx bx
  247.     ret
  248.     endp
  249.  
  250.     db    13,10
  251.     db    '                Too much is not enough...',13,10
  252.     db    '                            (Deep Purple)',13,10
  253.     db    13,10
  254.     db    'TMi0SDGL(tm) CPU/FPU feature detection library  Version 1.16BETA_2',13,10
  255.     db    'Copyright(c) 1992-95 by B-coolWare.     Released as freeware.',13,10
  256.  
  257. Test_Buffer    proc near
  258. ; this routine will never be called in DPMI applications for they won't run
  259. ; on CPU less that 286. Thus we need no precautions about writing to code
  260. ; segment.
  261.     push    es di
  262.     std
  263.     mov    _bpcs[@@0],41h
  264.     push    cs
  265.     pop    es
  266.     ldi    @@2
  267.     mov    al,_bpcs[@@1]
  268.     mov    cx,3
  269.     cli
  270.     rep    stosb
  271.     cld
  272.     nop
  273.     nop
  274.     nop
  275. @@0:    inc    cx
  276. @@1:
  277.     sti
  278. @@2:    
  279.     sti
  280.     pop    di es
  281.     ret
  282.     endp
  283.  
  284.     .386p
  285.  
  286. rdmsr    macro    Reg            ; new 486 and Pentium instruction
  287.     mov    ecx,Reg            ; read MSR #ECX into EDX:EAX
  288.     db    0Fh,32h
  289.     endm
  290. wrmsr    macro    Reg            ; new 486 and Pentium instruction
  291.     mov    ecx,Reg            ; write MSR #ECX from EDX:EAX
  292.     db    0Fh,30h
  293.     endm
  294.  
  295. checkIBMmsrs    proc    near
  296. ; we'll get here only on 386 with CPUID support
  297. ; returns CF=1 if IBM MSRs found and sets BL in this case
  298.     smsw    ax
  299.     test    al,1    ; we can only do this nasty code in real mode...
  300.     jz    @@OkWRMSR
  301.     call    checkQEMM    ; ...or under QEMM 7.04 and up.
  302.     jnc    @@Q
  303. @@OkWRMSR:
  304.     mov    eax,1
  305.     push    bx
  306.     cpuid
  307.     pop    bx
  308.     test    dx,20h        ; MSRs supported?
  309.     jnz    @@cont        ; yeah - check further
  310.     clc            ; nope - ain't IBM chip...
  311.     jmp    @@Q
  312. @@cont:
  313.     push    bx
  314.     rdmsr    1000h
  315.     push    edx eax    ; save MSR contents
  316.     xor    eax,40h    ; flip 'enable E000-E400 caching' bit
  317.     wrmsr    1000h    ; this probably won't go under most memory managers
  318.     rdmsr    1000h    ; read MSR back
  319.     pop    ecx ebx
  320.     cmp    ecx,eax
  321.     pushf
  322.     mov    eax,ecx
  323.     mov    edx,ebx
  324.     wrmsr    1000h    ; restore original MSR value
  325.     popf
  326.     pop    bx
  327.     jz    @@notflipped
  328.     stc
  329.     mov    bl,11h    ; IBM 386SLC
  330.     jmp    @@Q
  331. @@notflipped:
  332.     clc
  333. @@Q:
  334.     ret
  335.     endp
  336.  
  337. checkIBMmsrs2    proc    near
  338. ; we'll get here only on 486 with CPUID support
  339.     call    checkIBMmsrs    ; first check if this is IBM 486SLC chip
  340.     jnc    @@Q
  341.     push    bx
  342.     rdmsr    1002h        ; try to read 486SLC2 specific MSR
  343.     push    edx eax
  344.     xor    eax,20000000h    ; flip 'enable external dynamic frequency shift' bit
  345.     wrmsr    1002h        ; this probably won't go under most memory managers
  346.     rdmsr    1002h        ; read MSR back
  347.     pop    ecx ebx
  348.     cmp    ecx,eax
  349.     pushf
  350.     mov    eax,ecx
  351.     mov    edx,ebx
  352.     wrmsr    1002h        ; restore original MSR value
  353.     popf
  354.     pop    bx
  355.     jz    @@notSLC2    ; bit didn't flip - just a 486SLC
  356.     stc
  357.     mov    bl,13h        ; IBM 486SLC2
  358.     jmp    @@Q
  359. @@notSLC2:
  360.     stc
  361.     mov    bl,12h        ; IBM 486SLC
  362. @@Q:
  363.     ret
  364.     endp
  365.  
  366.     .8086
  367.  
  368. isInOSZwei    proc    near
  369.  
  370.     push    ax bx
  371.     mov    ax,4010h
  372.     int    2Fh
  373.     cmp    ax,4010h
  374.     pop    bx ax
  375.     ret
  376.     endp
  377.  
  378. checkWeitek    proc    near
  379.     cmp    bl,7
  380.     jb    @@1
  381.     .386
  382.     clr    eax
  383.     int    11h
  384.     test    eax,1000000h
  385.     .8086
  386.     jz    @@1
  387.     or    dl,1
  388. @@1:
  389.     ret
  390.     endp
  391.  
  392. fsbp0    equ    <db 0DBh,0E8h>
  393. fsbp1    equ    <db 0DBh,0EBh>
  394. fsbp2    equ    <db 0DBh,0EAh>
  395. fmul4x4    equ    <db 0DBh,0F1h>
  396.  
  397.  
  398. FPU_Type    proc near
  399.     .8086
  400.     .8087
  401.     push    ds
  402. ifdef    __DPMI__
  403.     push    ax bx
  404.     mov    ax,dpmiCreateCodeAlias
  405.     mov    bx,cs
  406.     int    31h
  407.     mov    ds,ax
  408.     pop    bx ax
  409. else
  410.     push    cs
  411.     pop    ds
  412.     ASSUME  DS:CPU_HL_TEXT
  413. endif
  414.     mov    dl,2
  415.     fninit
  416.     xor    cx,cx
  417.     jmp    $+2
  418.     mov    ds:fpudata1,5A5Ah
  419.     fnstsw    ds:fpudata1
  420.     mov    ax,ds:fpudata1
  421.     or    al,al
  422.     jnz    @@L15
  423.     fnstcw    ds:fpudata1
  424.     mov    ax,ds:fpudata1
  425.     and    ax,103Fh
  426.     cmp    ax,3Fh
  427.     jne    @@L15
  428.     mov    dl,4
  429.     fstenv    ds:fpudata3
  430.     fwait
  431.     and    ds:fpudata1,0FF7Fh
  432.     fldcw    ds:fpudata1
  433.     fwait
  434.     fdisi
  435.     fstcw    ds:fpudata1
  436.     fwait
  437.     test    ds:fpudata1,80h
  438.     jnz    @@L15
  439.     mov    dl,8
  440.     .286
  441.     .287
  442.     fninit
  443.     fld1
  444.     fldz
  445.     fdivp    st(1),st
  446.     fld    st
  447.     fchs
  448.     fcompp
  449.     fstsw    ds:fpudata1
  450.     fwait
  451.     mov    ax,ds:fpudata1
  452.     sahf
  453.     jz    @@L14
  454.     mov    dl,0Ch
  455. @@L14:
  456.     .286
  457.     .287
  458.  
  459.     cmp    bl,09h
  460.     jae    @@50
  461.     cmp    bl,06h
  462.     jb    @@50
  463.  
  464. @@checkIIT:
  465.     fninit
  466.     fsbp1
  467.     wait
  468.     fldz
  469.     fld1
  470.     fldz
  471.     fldz
  472.     fld1
  473.     fldz
  474.     fldz
  475.     fldz
  476.     wait
  477.     fninit
  478.     fsbp2
  479.     wait
  480.     fldz
  481.     fldz
  482.     fldz
  483.     fld1
  484.     fldz
  485.     fldz
  486.     fld1
  487.     fldz
  488.     wait
  489.     fninit
  490.     fsbp0
  491.     wait
  492.     fldz
  493.     fld1
  494.     fld    st(0)
  495.     fadd    st,st(0)
  496.     fld    st(0)
  497.     fadd    st,st(2)
  498.     fmul4x4
  499.     wait
  500.     fstp    ds:iit1
  501.     fstp    ds:iit2
  502.     fstp    ds:iit3
  503.     fstp    ds:iit4
  504.     wait
  505.     cmp    _wp ds:[iit4+2],4040h
  506.     jnz    @@50
  507.     cmp    _wp ds:[iit3+2],4000h
  508.     jnz    @@50
  509.     cmp    _wp ds:[iit2+2],3F80h
  510.     jnz    @@50
  511.     cmp    _wp ds:[iit1],0
  512.     jnz    @@50
  513.     cmp    dl,0Ch
  514.     jz    @@300
  515.     mov    dl,22
  516.     jmp    @@L15
  517. @@300:
  518.     mov    dl,24
  519.     jmp    @@L15
  520. @@50:
  521.     fninit
  522.     fldpi
  523.     f2xm1
  524.     fstp    ds:fpudata2
  525.     cmp    _wp ds:[fpudata2+2],3FC9h
  526.     jne    @@L15
  527.     or    dl,2
  528. @@L15:
  529.     cmp    bl,0Eh
  530.     jb    @@17
  531.     and    dl,3
  532.     or    dl,10h
  533.     jmp    @@30
  534. @@17:
  535.     cmp    bl,0Bh
  536.     jnz    @@L17
  537.     cmp    dl,3
  538.     ja    @@builtin
  539.     dec    bl
  540.     jmp    @@31
  541. @@builtin:
  542.     and    dl,1
  543.     or    dl,10h
  544.     jmp    @@nobuilt
  545. @@L17:
  546.     cmp    bl,0Eh
  547.     jae    @@builtin
  548.     cmp    bl,0Dh
  549.     jnz    @@nobuilt
  550.     cmp    dl,12h
  551.     jz    @@builtin
  552.     cmp    dl,13h
  553.     jz    @@builtin
  554. @@nobuilt:
  555.     cmp    bl,06
  556.     jnz    @@30
  557.     cmp    dl,0Ch
  558.     jz    @@XL
  559.     cmp    dl,0Dh
  560.     jnz    @@30
  561. @@XL:
  562.     add    dl,8
  563. @@30:
  564.     cmp    bl,0Ch
  565.     jz    @@is387
  566.     cmp    bl,0Ah
  567.     jnz    @@31
  568. @@is387:
  569.     cmp    dl,0Ch
  570.     jz    @@487sx
  571.     cmp    dl,0Dh
  572.     jnz    @@31
  573. @@487sx:
  574.     and    dl,1
  575.     or    dl,6    
  576. @@31:
  577.     cmp    dl,4
  578.     jb    @@L18
  579.     fldenv    ds:fpudata3
  580. @@L18:
  581. ifdef    __DPMI__
  582.     push    ax bx
  583.     mov    ax,dpmiFreeLDTDesc
  584.     mov    bx,ds
  585.     int    31h
  586.     pop    bx ax
  587. endif
  588.     pop    ds
  589.     ASSUME    DS:DGROUP
  590.     ret
  591.     endp
  592. fpudata1    dw    ?
  593. fpudata2    dd    ?
  594. fpudata3    db    14 dup(?)
  595.  
  596. iit1        dd    6F772049h
  597. iit2        dd    7265646Eh
  598. iit3        dd    20666920h
  599. iit4        dd    00544949h
  600.  
  601. checkEmu    proc
  602.     .286p
  603.     smsw    ax
  604.     test    al,04
  605.     mov    al,1
  606.     jnz    @@1
  607.     clr    al
  608. @@1:
  609.     ret
  610.     endp
  611.  
  612. ;checkAMD    proc
  613. ;IFNDEF    __DPMI__
  614. ;    push    ds
  615. ;    mov    ax,3506h
  616. ;    int    21h
  617. ;    push    cs
  618. ;    pop    ds
  619. ;    mov    dx,offset @@int6Trap
  620. ;    mov    ax,2506h
  621. ;    int    21h
  622. ;    sub    cx,cx
  623. ;    db    0F0h,90h    ; LOCK NOP causes INT 6 on AMD chips,
  624. ;                ; though it works ok in Intel ones.
  625. ;@@afterTrap:
  626. ;    push    es
  627. ;    pop    ds
  628. ;    mov    dx,bx
  629. ;    mov    ax,2506h
  630. ;    int    21h
  631. ;    mov    ax,cx
  632. ;    pop    ds
  633. ;    ret
  634. ;@@int6Trap:
  635. ;    add    sp,4
  636. ;    popf
  637. ;    inc    cx
  638. ;    jmp    @@afterTrap
  639. ;ELSE
  640. ;    mov    ax,dpmiGetExceptionHnd
  641. ;    mov    bl,06h
  642. ;    int    31h
  643. ;    push    cx dx
  644. ;    mov    ax,dpmiSetExceptionHnd
  645. ;    mov    bl,06h
  646. ;    push    cs
  647. ;    pop    cx
  648. ;    mov    dx,offset @@int6Trap
  649. ;    int    31h
  650. ;    mov    si,1
  651. ;    db    0F0h,90h
  652. ;    dec    si
  653. ;@@afterTrap:
  654. ;    pop    dx cx
  655. ;    mov    ax,dpmiSetExceptionHnd
  656. ;    mov    bl,06h
  657. ;    int    31h
  658. ;    mov    ax,si
  659. ;    ret
  660. ;@@int6Trap:
  661. ;    push    bp
  662. ;    mov    bp,sp
  663. ;    mov    word ptr ss:[bp+8],offset @@afterTrap    ; modify IP on stack
  664. ;    pop    bp
  665. ;    retf
  666. ;ENDIF
  667. ;    endp
  668.  
  669.  
  670. getQEMMAPI    proc    near
  671. ; get QEMM API entry point
  672. ; returns CF=1 if QEMM found and API entry point got OK.
  673.     ldx    QEMMId
  674.     mov    ax,3D00h
  675.     clr    cx
  676.     int    21h
  677.     jc    @@Q
  678.     mov    bx,ax
  679.     mov    ax,4402h
  680.     mov    cx,4
  681.     ldx    QEMMEntry
  682.     int    21h
  683.     mov    ah,3Eh
  684.     int    21h
  685.     clc
  686. @@Q:
  687.     ret
  688.     endp
  689.  
  690. checkQEMM    proc    near
  691. ; get and check QEMM version. Only QEMM v7.04 and up enables WRMSR from V86.
  692. ; returns CF=1 if QEMM found and version is OK.
  693.     push    bx
  694.     call    getQEMMAPI
  695.     jc    @@tooearly
  696.     mov    ah,3
  697.     call    dword ptr ds:QEMMEntry
  698.     cmp    bx,0704h
  699.     pop    bx
  700.     jb    @@tooearly
  701.     stc
  702.     ret
  703. @@tooearly:
  704.     clc
  705.     ret
  706.     endp
  707.  
  708.     EXTRN    QEMMEntry : DWORD
  709.     EXTRN    QEMMId      : BYTE
  710.  
  711.     END
  712.