home *** CD-ROM | disk | FTP | other *** search
- ; -----------------------------------------------------------------------------
- ; CPU_HL.ASM CPU Type detection routine for hi-level languages Version 1.16B2
- ;
- ; Too-Much-In-One-So-Don't-Get-Lost(tm) CPU/FPU feature detection library
- ;
- ; Copyright(c) 1992-95 by B-coolWare. Written by Bobby Z.
- ; -----------------------------------------------------------------------------
- ; This is a port from CPU_TYPE.ASH - the assembler version of TMi0SDGL(tm)
- ; See file CPU_TYPE.ASH for extensive comments and all.
-
- INCLUDE HEADER.ASH
-
- .DATA
-
- EXTRN FPUType:BYTE
-
- .CODE
-
- PUBLIC CPU_Type
- PUBLIC checkEmu
- ; PUBLIC checkAMD
-
- ; TP/BP:
- ; function CPU_Type : Word;
- ;
- ; C/C++:
- ; word CPU_Type(void);
- ;
- ; returns current CPU code (see CPUTYPE.PAS or CPUTYPE.H for details) and sets
- ; current FPU code in FPUType variable.
-
- EF_AC equ 00040000h ; AC bit in EFLAGS register
- EF_ID equ 00200000h ; ID bit in EFLAGS register
- MSW_NE equ 00000020h ; NE bit in MSW register
-
- cpuid equ <db 0Fh,0A2h> ; new i486 & Pentium instruction
-
- CPU_Type proc
- .8086
- push bx cx si
- sub bx,bx
- push sp
- pop ax
- cmp ax,sp
- jnz @@Ct_000
- mov ax,7000h
- pushf
- push ax
- popf
- pushf
- pop ax
- popf
- mov bl,6
- and ax,7000h
- jz @@Ct_200
- inc bx
-
- .386p
- clr si
- mov eax,cr0
- mov ecx,eax
- xor eax,10h
- mov cr0,eax
- mov eax,cr0
- mov cr0,ecx
- xor eax,ecx
- jz @@L100
- inc si
-
- @@L100:
-
- .386
-
- mov ax,sp
- and sp,0FFFCh
- pushfd
- pushfd
- pop edx
- mov ecx,edx
- xor edx,EF_AC
- and ecx,EF_AC
- push edx
- popfd
- pushfd
- pop edx
- popfd
- mov sp,ax
- and edx,EF_AC
- cmp edx,ecx
- jnz @@486
- or si,si
- jz @@L1
- inc bx
- jmp @@L1
-
- @@486:
- mov bx,0Ah
- push bx
- mov bx,100h
- mov ah,7Fh
- cwd
- sahf
- div bx
- lahf
- xor al,ah
- and al,0D5h
- pop bx
- jnz @@586
- inc bx
- inc bx
- or si,si
- jz @@586
- inc bx
- @@586:
-
- pushfd
- pop eax
- mov ecx,eax
- xor eax,EF_ID
- push eax
- popfd
- pushfd
- pop eax
- push ecx
- popfd
- and eax,EF_ID
- and ecx,EF_ID
- cmp eax,ecx
- jz @@486sdx
- clr eax
- inc al
- push bx
- cpuid
- pop bx
- and ah,0Fh
- cmp ah,4
- jb @@386dx
- je @@486sdx2
- cmp bl,0Ch
- jb @@P5
- cmp bl,0Dh
- ja @@P5
- mov bl,0Fh
- jmp @@L1
- @@P5:
- mov bl,ah
- cmp bl,6
- jz @@P6
- add bl,9
- jmp @@L1
- @@P6:
- mov bl,18h
- jmp @@L1
- @@386dx:
- call checkIBMmsrs
- jc @@L1
- mov bx,7
- or si,si
- jz @@L1
- inc bx
- jmp @@L1
- @@486sdx2:
- call checkIBMmsrs2
- jc @@L1
- mov bl,0Ah
- push bx
- clr eax
- inc al
- cpuid
- pop bx
- and ax,03F0h
- cmp ah,10h ; type field set to 01 means this is Pentium Overdrive
- jz @@P24D
- @@noP24:
- test al,al
- jnz @@setNibble
- inc al
- @@setNibble:
- or bh,al
- jmp @@L1
- @@P24D:
- mov bl,10h
- jmp @@L1
-
- @@486sdx:
- .486p
- call isInOSZwei
- jnz @@L1
- cmp bl,0Dh
- jae @@L1
- mov eax,cr0
- mov ecx,eax
- db 66h,83h,0E0h,0DFh
- mov cr0,eax
- mov eax,cr0
- cmp eax,ecx
- jnz @@486dx
- or eax,MSW_NE
- mov cr0,eax
- mov eax,cr0
- cmp eax,ecx
- jnz @@486dx
- dec bx
- @@486dx:
- inc bx
- mov eax,ecx
- mov cr0,eax
-
- @@L1:
- .286p
- smsw ax
- and al,1
- or bh,al
- jmp @@Ct_200
- @@Ct_000:
- mov bl,4
- mov cl,33
- clr ax
- dec ax
- shl ax,cl
- jnz @@Ct_100
- mov bl,2
- clr cx
- dec cx
- db 0F3h,26h,0ACh
- jcxz @@Ct_100
- clr bx
- @@Ct_100:
- clr ax
- call Test_Buffer
- jcxz @@Ct_200
- inc bx
- @@Ct_200:
- test ah,0F0h
- jz @@checkFPU
- test dl,1
- jz @@checkFPU
- mov dl,10h
- jmp @@noCheck
- @@checkFPU:
- call FPU_Type
- @@noCheck:
- call checkWeitek
- mov FPUType,dl
- mov ax,bx
- pop si cx bx
- ret
- endp
-
- db 13,10
- db ' Too much is not enough...',13,10
- db ' (Deep Purple)',13,10
- db 13,10
- db 'TMi0SDGL(tm) CPU/FPU feature detection library Version 1.16BETA_2',13,10
- db 'Copyright(c) 1992-95 by B-coolWare. Released as freeware.',13,10
-
- Test_Buffer proc near
- ; this routine will never be called in DPMI applications for they won't run
- ; on CPU less that 286. Thus we need no precautions about writing to code
- ; segment.
- push es di
- std
- mov _bpcs[@@0],41h
- push cs
- pop es
- ldi @@2
- mov al,_bpcs[@@1]
- mov cx,3
- cli
- rep stosb
- cld
- nop
- nop
- nop
- @@0: inc cx
- @@1:
- sti
- @@2:
- sti
- pop di es
- ret
- endp
-
- .386p
-
- rdmsr macro Reg ; new 486 and Pentium instruction
- mov ecx,Reg ; read MSR #ECX into EDX:EAX
- db 0Fh,32h
- endm
- wrmsr macro Reg ; new 486 and Pentium instruction
- mov ecx,Reg ; write MSR #ECX from EDX:EAX
- db 0Fh,30h
- endm
-
- checkIBMmsrs proc near
- ; we'll get here only on 386 with CPUID support
- ; returns CF=1 if IBM MSRs found and sets BL in this case
- smsw ax
- test al,1 ; we can only do this nasty code in real mode...
- jz @@OkWRMSR
- call checkQEMM ; ...or under QEMM 7.04 and up.
- jnc @@Q
- @@OkWRMSR:
- mov eax,1
- push bx
- cpuid
- pop bx
- test dx,20h ; MSRs supported?
- jnz @@cont ; yeah - check further
- clc ; nope - ain't IBM chip...
- jmp @@Q
- @@cont:
- push bx
- rdmsr 1000h
- push edx eax ; save MSR contents
- xor eax,40h ; flip 'enable E000-E400 caching' bit
- wrmsr 1000h ; this probably won't go under most memory managers
- rdmsr 1000h ; read MSR back
- pop ecx ebx
- cmp ecx,eax
- pushf
- mov eax,ecx
- mov edx,ebx
- wrmsr 1000h ; restore original MSR value
- popf
- pop bx
- jz @@notflipped
- stc
- mov bl,11h ; IBM 386SLC
- jmp @@Q
- @@notflipped:
- clc
- @@Q:
- ret
- endp
-
- checkIBMmsrs2 proc near
- ; we'll get here only on 486 with CPUID support
- call checkIBMmsrs ; first check if this is IBM 486SLC chip
- jnc @@Q
- push bx
- rdmsr 1002h ; try to read 486SLC2 specific MSR
- push edx eax
- xor eax,20000000h ; flip 'enable external dynamic frequency shift' bit
- wrmsr 1002h ; this probably won't go under most memory managers
- rdmsr 1002h ; read MSR back
- pop ecx ebx
- cmp ecx,eax
- pushf
- mov eax,ecx
- mov edx,ebx
- wrmsr 1002h ; restore original MSR value
- popf
- pop bx
- jz @@notSLC2 ; bit didn't flip - just a 486SLC
- stc
- mov bl,13h ; IBM 486SLC2
- jmp @@Q
- @@notSLC2:
- stc
- mov bl,12h ; IBM 486SLC
- @@Q:
- ret
- endp
-
- .8086
-
- isInOSZwei proc near
-
- push ax bx
- mov ax,4010h
- int 2Fh
- cmp ax,4010h
- pop bx ax
- ret
- endp
-
- checkWeitek proc near
- cmp bl,7
- jb @@1
- .386
- clr eax
- int 11h
- test eax,1000000h
- .8086
- jz @@1
- or dl,1
- @@1:
- ret
- endp
-
- fsbp0 equ <db 0DBh,0E8h>
- fsbp1 equ <db 0DBh,0EBh>
- fsbp2 equ <db 0DBh,0EAh>
- fmul4x4 equ <db 0DBh,0F1h>
-
-
- FPU_Type proc near
- .8086
- .8087
- push ds
- ifdef __DPMI__
- push ax bx
- mov ax,dpmiCreateCodeAlias
- mov bx,cs
- int 31h
- mov ds,ax
- pop bx ax
- else
- push cs
- pop ds
- ASSUME DS:CPU_HL_TEXT
- endif
- mov dl,2
- fninit
- xor cx,cx
- jmp $+2
- mov ds:fpudata1,5A5Ah
- fnstsw ds:fpudata1
- mov ax,ds:fpudata1
- or al,al
- jnz @@L15
- fnstcw ds:fpudata1
- mov ax,ds:fpudata1
- and ax,103Fh
- cmp ax,3Fh
- jne @@L15
- mov dl,4
- fstenv ds:fpudata3
- fwait
- and ds:fpudata1,0FF7Fh
- fldcw ds:fpudata1
- fwait
- fdisi
- fstcw ds:fpudata1
- fwait
- test ds:fpudata1,80h
- jnz @@L15
- mov dl,8
- .286
- .287
- fninit
- fld1
- fldz
- fdivp st(1),st
- fld st
- fchs
- fcompp
- fstsw ds:fpudata1
- fwait
- mov ax,ds:fpudata1
- sahf
- jz @@L14
- mov dl,0Ch
- @@L14:
- .286
- .287
-
- cmp bl,09h
- jae @@50
- cmp bl,06h
- jb @@50
-
- @@checkIIT:
- fninit
- fsbp1
- wait
- fldz
- fld1
- fldz
- fldz
- fld1
- fldz
- fldz
- fldz
- wait
- fninit
- fsbp2
- wait
- fldz
- fldz
- fldz
- fld1
- fldz
- fldz
- fld1
- fldz
- wait
- fninit
- fsbp0
- wait
- fldz
- fld1
- fld st(0)
- fadd st,st(0)
- fld st(0)
- fadd st,st(2)
- fmul4x4
- wait
- fstp ds:iit1
- fstp ds:iit2
- fstp ds:iit3
- fstp ds:iit4
- wait
- cmp _wp ds:[iit4+2],4040h
- jnz @@50
- cmp _wp ds:[iit3+2],4000h
- jnz @@50
- cmp _wp ds:[iit2+2],3F80h
- jnz @@50
- cmp _wp ds:[iit1],0
- jnz @@50
- cmp dl,0Ch
- jz @@300
- mov dl,22
- jmp @@L15
- @@300:
- mov dl,24
- jmp @@L15
- @@50:
- fninit
- fldpi
- f2xm1
- fstp ds:fpudata2
- cmp _wp ds:[fpudata2+2],3FC9h
- jne @@L15
- or dl,2
- @@L15:
- cmp bl,0Eh
- jb @@17
- and dl,3
- or dl,10h
- jmp @@30
- @@17:
- cmp bl,0Bh
- jnz @@L17
- cmp dl,3
- ja @@builtin
- dec bl
- jmp @@31
- @@builtin:
- and dl,1
- or dl,10h
- jmp @@nobuilt
- @@L17:
- cmp bl,0Eh
- jae @@builtin
- cmp bl,0Dh
- jnz @@nobuilt
- cmp dl,12h
- jz @@builtin
- cmp dl,13h
- jz @@builtin
- @@nobuilt:
- cmp bl,06
- jnz @@30
- cmp dl,0Ch
- jz @@XL
- cmp dl,0Dh
- jnz @@30
- @@XL:
- add dl,8
- @@30:
- cmp bl,0Ch
- jz @@is387
- cmp bl,0Ah
- jnz @@31
- @@is387:
- cmp dl,0Ch
- jz @@487sx
- cmp dl,0Dh
- jnz @@31
- @@487sx:
- and dl,1
- or dl,6
- @@31:
- cmp dl,4
- jb @@L18
- fldenv ds:fpudata3
- @@L18:
- ifdef __DPMI__
- push ax bx
- mov ax,dpmiFreeLDTDesc
- mov bx,ds
- int 31h
- pop bx ax
- endif
- pop ds
- ASSUME DS:DGROUP
- ret
- endp
- fpudata1 dw ?
- fpudata2 dd ?
- fpudata3 db 14 dup(?)
-
- iit1 dd 6F772049h
- iit2 dd 7265646Eh
- iit3 dd 20666920h
- iit4 dd 00544949h
-
- checkEmu proc
- .286p
- smsw ax
- test al,04
- mov al,1
- jnz @@1
- clr al
- @@1:
- ret
- endp
-
- ;checkAMD proc
- ;IFNDEF __DPMI__
- ; push ds
- ; mov ax,3506h
- ; int 21h
- ; push cs
- ; pop ds
- ; mov dx,offset @@int6Trap
- ; mov ax,2506h
- ; int 21h
- ; sub cx,cx
- ; db 0F0h,90h ; LOCK NOP causes INT 6 on AMD chips,
- ; ; though it works ok in Intel ones.
- ;@@afterTrap:
- ; push es
- ; pop ds
- ; mov dx,bx
- ; mov ax,2506h
- ; int 21h
- ; mov ax,cx
- ; pop ds
- ; ret
- ;@@int6Trap:
- ; add sp,4
- ; popf
- ; inc cx
- ; jmp @@afterTrap
- ;ELSE
- ; mov ax,dpmiGetExceptionHnd
- ; mov bl,06h
- ; int 31h
- ; push cx dx
- ; mov ax,dpmiSetExceptionHnd
- ; mov bl,06h
- ; push cs
- ; pop cx
- ; mov dx,offset @@int6Trap
- ; int 31h
- ; mov si,1
- ; db 0F0h,90h
- ; dec si
- ;@@afterTrap:
- ; pop dx cx
- ; mov ax,dpmiSetExceptionHnd
- ; mov bl,06h
- ; int 31h
- ; mov ax,si
- ; ret
- ;@@int6Trap:
- ; push bp
- ; mov bp,sp
- ; mov word ptr ss:[bp+8],offset @@afterTrap ; modify IP on stack
- ; pop bp
- ; retf
- ;ENDIF
- ; endp
-
-
- getQEMMAPI proc near
- ; get QEMM API entry point
- ; returns CF=1 if QEMM found and API entry point got OK.
- ldx QEMMId
- mov ax,3D00h
- clr cx
- int 21h
- jc @@Q
- mov bx,ax
- mov ax,4402h
- mov cx,4
- ldx QEMMEntry
- int 21h
- mov ah,3Eh
- int 21h
- clc
- @@Q:
- ret
- endp
-
- checkQEMM proc near
- ; get and check QEMM version. Only QEMM v7.04 and up enables WRMSR from V86.
- ; returns CF=1 if QEMM found and version is OK.
- push bx
- call getQEMMAPI
- jc @@tooearly
- mov ah,3
- call dword ptr ds:QEMMEntry
- cmp bx,0704h
- pop bx
- jb @@tooearly
- stc
- ret
- @@tooearly:
- clc
- ret
- endp
-
- EXTRN QEMMEntry : DWORD
- EXTRN QEMMId : BYTE
-
- END
-