📄 cpu_type.ash
字号:
ifdef __386STEP__
stepB0 EQU 0
stepB1 EQU 1
stepD0 EQU 2
ifdef __PRINT_STEP__
stepTable label word
dw offset B0Str
dw offset B1Str
dw offset D0Str
Lstring B0Str,<B0 or earlier>
Lstring B1Str,<B1>
Lstring D0Str,<D0 or later>
Lstring stepStr,<, chip step is >
print_Step proc
.8086
ldx stepStr
call WriteStr
call i386step
mov bl,al
clr bh
shl bx,1
mov dx,stepTable[bx]
call WriteStr
ret
endp
endif
; this routine determines 386DX chip stepping.
; ripped from Phar Lap TellMe utility.
; returns:
; ax = 0 -> chip is step B0 or earlier
; ax = 1 -> chip is step B1
; ax = 2 -> chip is step D0 or later
i386step proc
.386
push bx cx dx si di es ds
mov ax,3506h
int 21h
push cs
pop ds
mov dx,offset @@int06h
mov ax,2506h
int 21h
clr cx
inc cx
; .486
; cmpxchg ds:[bx+si],al ; this command sequence cause INT 06
db 0Fh,0A6h,00h ; to occur on 386s later than step B0.
; TASM does not generate this code when
; using mnemonics. Generated code
; differs from that specified in db
; but decodes in the same instruction.
@@B0:
mov dx,bx
push es
pop ds
mov ax,2506h
int 21h
jcxz @@checkB1
clr ax
jmp @@Qstep
@@int06h:
clr cx
add sp,4
popf
jmp @@B0
@@buf dw 0
@@checkB1:
mov di,offset @@buf
mov dx,80h
inc cx ; cx = 0 if we got here
mov ax,cx
inc ax
cld
push ax
rep insb ; repeating insb 1 times on B1 step chip does
; not reset cx to zero.
pop ax
jcxz @@Qstep
dec ax
@@Qstep:
pop ds es di si dx cx bx
ret
endp
endif
ifdef __PRINT_FPU__
FPUs dw offset fpuUnknown ; ?
dw offset fpuUnknown ; ?
dw offset fpuNone ; ---
dw offset fpuWeitek ; Weitek
dw offset fpu87 ; 8087
dw offset fpu87W ; 8087 + Weitek
dw offset fpu487sx ; i487sx
dw offset fpu487sxw ; i487sx + Weitek
dw offset fpu287 ; 80287
dw offset fpu287W ; 80287 + Weitek
dw offset fpu2C87 ; Cyrix 2C87
dw offset fpu2C87W ; Cyrix 2C87 + Weitek
dw offset fpu387 ; 80387
dw offset fpu387W ; 80387 + Weitek
dw offset fpu3C87 ; Cyrix 3C87
dw offset fpu3C87W ; Cyrix 3C87 + Weitek
dw offset fpuBuiltIn ; 486 internal
dw offset fpuBuiltInW ; 486 internal + Weitek
dw offset fpu4C87 ; Cyrix 4C87
dw offset fpu4C87W ; Cyrix 4C87 + Weitek
dw offset fpu287XL ; Intel 80287XL
dw offset fpu287XLW ; Intel 80287XL + Weitek
dw offset fpuIIT2C87 ; IIT 2C87
dw offset fpuIIT2C87W ; IIT 2C87 + Weitek
dw offset fpuIIT3C87 ; IIT 3C87
dw offset fpuIIT3C87W ; IIT 3C87 + Weitek
dw offset fpuULSI83C87 ; ULSI 83C87
dw offset fpuULSI83C87W ; ULSI 83C87 + Weitek
dw offset fpuEMC87 ; Intel EMC87
dw offset fpuEMC87W ; Intel EMC87 + Weitek
dw offset fpuCT ; C&T 38700
dw offset fpuCTW ; C&T 38700 + Weitek
dw offset Nx587 ; NexGen Nx587
dw offset Nx587W ; NexGen Nx587 + Weitek
dw offset fpuIIT4C87 ; IIT 4C87
dw offset fpuIIT4C87W ; IIT 4C87 + Weitek
Lstring SLEnhanced,< [SL Enhanced]>
Lstring FPUis,<Coprocessor: >
Lstring fpuWeitek,<Weitek>
Lstring fpuUnknown,<Unknown>
Lstring fpuNone,<None>
Lstring fpuBuiltIn,<Internal>
Lstring fpu87,<Intel 8087>
Lstring fpu287,<Intel 80287>
Lstring fpu287XL,<Intel 80287XL>
Lstring fpu387,<Intel 80387>
Lstring fpu487sx,<Intel i487sx>
Lstring fpu2C87,<Cyrix 82x87>
Lstring fpu3C87,<Cyrix 83x87>
Lstring fpu4C87,<Cyrix 84x87>
Lstring fpuULSI83C87,<ULSI 83x87>
Lstring fpuEMC87,<Cyrix EMC87>
Lstring fpuCT,<C&T 38700>
Lstring fpuIIT2C87,<IIT 2C87>
Lstring fpuIIT3C87,<IIT 3C87>
Lstring fpuIIT4C87,<IIT 4C87>
Lstring Nx587,<NexGen Nx587>
Lstring fpu487sxw,<Intel i487sx and Weitek>
Lstring fpuBuiltInW,<Internal and Weitek>
Lstring fpu87W,<Intel 8087 and Weitek>
Lstring fpu287W,<Intel 80287 and Weitek>
Lstring fpu287XLW,<Intel 80287XL and Weitek>
Lstring fpuIIT2C87W,<IIT 2C87 and Weitek>
Lstring fpuIIT3C87W,<IIT 3C87 and Weitek>
Lstring fpuIIT4C87W,<IIT 4C87 and Weitek>
Lstring fpu387W,<Intel 80387 and Weitek>
Lstring fpu2C87W,<Cyrix 2C87 and Weitek>
Lstring fpu3C87W,<Cyrix 3C87 and Weitek>
Lstring fpu4C87W,<Cyrix 4C87 and Weitek>
Lstring fpuULSI83C87W,<ULSI 83x87 and Weitek>
Lstring fpuEMC87W,<Cyrix EMC87 and Weitek>
Lstring fpuCTW,<C&T 38700 and Weitek>
Lstring Nx587W,<NexGen Nx587 and Weitek>
Lstring EndLine,<>,CrLf
Lstring Emulator,<, Emulated>
print_FPU proc
ldx FPUis
call WriteStr
mov bx,FPUType
shl bx,1
mov dx,FPUs[bx]
call WriteStr
cmp al,cpu286
jb @@1p
call checkEmu
jnc @@1p
ldx Emulator
call WriteStr
@@1p:
ret
endp
endif
.386p
IF ??version LT 400h
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
ENDIF
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
push dx
smsw ax
test al,1 ; we can only do this nasty code in real mode...
jnz @@Qs1
; jz @@OkWRMSR
; call checkQEMM ; ...or under QEMM 7.04 and up. ???
; jnc @@Qs1
;@@OkWRMSR:
push bx
push ds
mov ax,350Dh
int 21h
push es
push bx
push cs
pop ds
mov dx,offset @@trap0D
mov ax,250Dh ; intercept GPF exception
int 21h
mov ax,3506h
int 21h
push es
push bx
mov dx,offset @@trap06
mov ax,2506h ; and Invalid Instruction exception
int 21h
IF ??version LT 400h
rdmsr 1000h
ELSE
mov ecx,1000h
.586p
rdmsr
ENDIF ; We'll get Exception 13 if this MSR is not
stc ; valid or Exception 06 if this is not IBM386.
mov bl,ibm3slc ; IBM 386SLC
jmp @@Qs
@@trap06:
add sp,4
popf
clc
jmp @@Qs
@@trap0D:
add sp,4
popf
clc
@@Qs:
pop dx
pop ds
pushf
mov ax,2506h
int 21h
popf
pop dx
pop ds
pushf
mov ax,250Dh
int 21h
popf
pop ds
pop bx
@@Qs1:
pop dx
ret
endp
checkIBMmsrs2 proc near
; we'll get here only on 486 with CPUID support
push dx
call checkIBMmsrs ; first check if this is IBM 486SLC chip
jnc @@Qi
push bx
push ds
mov ax,350Dh ; we don't need to intercept Exception #6 here,
int 21h ; for it is proved that RDMSR instruction is
push es ; valid for current CPU. But the register we're
push bx ; trying to read may be invalid...
push cs
pop ds
mov dx,offset @@trap0D2
mov ax,250Dh
int 21h
IF ??version LT 400h
rdmsr 1002h ; try to read 486SLC2 specific MSR
ELSE
mov ecx,1002h
.586p
rdmsr
ENDIF
mov bl,ibm4slc2 ; IBM 486SLC2
jmp @@Qi2
@@trap0D2:
add sp,4
popf
stc
mov bl,ibm4slc ; IBM 486SLC
@@Qi2:
pop dx
pop ds
pushf
mov ax,250Dh
int 21h
popf
pop bx
@@Qi:
pop dx
ret
endp
checkIBMmsrs3 proc near
; we'll get here only on 486 with CPUID support
push dx
call checkIBMmsrs2
jnc @@Qi4
push bx
push ds
mov ax,350Dh ; we don't need to intercept Exception #6 here,
int 21h ; for it is proved that RDMSR instruction is
push es ; valid for current CPU. But the register we're
push bx ; trying to read may be invalid...
push cs
pop ds
mov dx,offset @@trap0D3
mov ax,250Dh
int 21h
IF ??version LT 400h
rdmsr 1004h ; try to read 486BL3 specific MSR
ELSE
mov ecx,1004h
.586p
rdmsr
ENDIF
mov bl,ibm4bl3
jmp @@Qi3
@@trap0D3:
add sp,4
popf
stc
@@Qi3:
pop dx
pop ds
pushf
mov ax,250Dh
int 21h
popf
pop bx
@@Qi4:
pop dx
ret
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 @@Qa
; mov bx,ax
; mov ax,4402h
; mov cx,4
; ldx QEMMEntry
; int 21h
; mov ah,3Eh
; int 21h
; clc
;@@Qa:
; 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
;
;QEMMEntry dd ?
;QEMMId db 'QEMM386$',0
.386
read_chipset macro
; macro for reading chipset register specified in AL
out 22h,al
in al,23h
endm
write_chipset macro
; macro for writing a value in AH to chipset register specified in AL
out 22h,al
mov al,ah
out 23h,al
endm
getCyrixModel proc
pushf
cli
clr dx
mov al,0C2h
read_chipset
mov cl,al
or al,4
mov bh,al
mov ah,al
mov al,0C2h
write_chipset
mov al,0C0h
read_chipset
mov al,0C2h
read_chipset
or al,4
cmp al,4
jne @@4
mov al,cl
and al,not 4
mov ah,al
mov al,0C2h
write_chipset
mov al,0C0h
read_chipset
mov al,0C2h
read_chipset
and al,4
jnz @@4
inc dh
@@4:
mov al,0C2h
mov ah,cl
write_chipset
mov al,0C3h
read_chipset
mov cl,al
or al,2
mov bh,al
mov ah,al
mov al,0C3h
write_chipset
mov al,0C0h
read_chipset
mov al,0C3h
read_chipset
or al,2
cmp al,2
jne @@5
mov al,cl
and al,not 2
mov ah,al
mov al,0C3h
write_chipset
mov al,0C0h
read_chipset
mov al,0C3h
read_chipset
and al,2
jnz @@5
inc dl
@@5:
mov al,0C3h
mov ah,cl
write_chipset
test dl,dl
jz @@6
clr bx
clr cx
mov al,0FEh
read_chipset
mov bl,al ; bl = DIR0
mov al,0FFh
read_chipset
mov bh,al ; bh = DIR1
jmp @@7
@@6:
clr bx ; unknown Cyrix chip
@@7:
sti
mov ax,bx
popf
ret
endp
int6H: ; INT 6 (invalid instruction) trap hook
clr ax
add sp,4 ; restore stack and jump past offending instruction
popf
jmp Past_invalid
isSMMAble proc
push ds
mov ax,3506h ; get current INT 6 vector
int 21h
mov ax,2506h ; hook INT 6
mov dx,offset int6H
push cs
pop ds
int 21h
pop ds
clr ax ; AX = 0
mov cl,1 ; CL = 1
mov dl,ds:[bx+si] ; save byte at [bx+si] in dl
; The following code ( 0F12C1 ) is SMM instruction UMOV AL,CL that moves
; data from/to main memory nevertheless the processor is in SMM or not.
; Cyrix chips doesn't generate INT 6 on this instruction. Instead, two
; bytes 0F12 gets skipped and the next instruction appears to be
; {rol word ptr [bx+si],0} ( C10000 ).
db 0Fh
adc al,cl
add ds:[bx+si],al
Past_Invalid:
mov ds:[bx+si],dl ; restoring possibly damaged data
push ds
push es
pop ds
mov dx,bx
push ax
mov ax,2506h ; restore INT 6 vector
int 21h
pop ax
pop ds
ret
endp
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -