windows-nt/Source/XPSP1/NT/base/boot/lib/i386/cpu386.asm
2020-09-26 16:20:57 +08:00

253 lines
6.2 KiB
NASM

title "Processor type and stepping detection"
;++
;
; Copyright (c) 1989 Microsoft Corporation
;
; Module Name:
;
; cpu.asm
;
; Abstract:
;
; This module implements the assembley code necessary to determine
; cpu type and stepping information.
;
; Author:
;
; Shie-Lin Tzong (shielint) 28-Oct-1991.
;
; Environment:
;
; 80x86
;
; Revision History:
;
;--
.586p
.xlist
include mac386.inc
include callconv.inc
.list
_TEXT SEGMENT DWORD PUBLIC 'CODE'
ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
CR0_AM equ 40000h
EFLAGS_AC equ 40000h
subttl "Is386"
;++
;
; BOOLEAN
; BlIs386(
; VOID
; )
;
; Routine Description:
;
; This function determines whether the processor we're running on
; is a 386. If not a 386, it is assumed that the processor is
; a 486 or greater.
;
; Arguments:
;
; None.
;
; Return Value:
;
; (al) = 1 - processor is a 386
; (al) = 0 - processor is a 486 or greater.
;
;--
public _BlIs386@0
_BlIs386@0 proc
mov eax,cr0
push eax ; save current cr0
and eax,not CR0_AM ; mask out alignment check bit
mov cr0,eax ; disable alignment check
pushfd ; save flags
pushfd ; turn on alignment check bit in
or dword ptr [esp],EFLAGS_AC ; a copy of the flags register
popfd ; and try to load flags
pushfd
pop ecx ; get new flags into ecx
popfd ; restore original flags
pop eax ; restore original cr0
mov cr0,eax
xor al,al ; prepare for return, assume not 386
and ecx,EFLAGS_AC ; did AC bit get set?
jnz short @f ; yes, we don't have a 386
inc al ; we have a 386
@@: ret
_BlIs386@0 endp
subttl "IsCpuidPresent"
;++
;
; BOOLEAN
; BlIsCpuidPresent(
; VOID
; )
;
; Routine Description:
;
; If bit 21 of the EFLAGS register is writable, CPUID is supported on
; this processor. If not writable, CPUID is not supported.
;
; Note: It is expected that this routine is "locked" onto a single
; processor when run.
;
; Arguments:
;
; None.
;
; Return Value:
;
; TRUE if CPUID is supported,
; FALSE otherwise.
;
;--
EFLAGS_ID equ 200000h ; bit 21
cPublicProc _BlIsCpuidPresent ,0
pushfd ; save EFLAGS
pop ecx ; get current value
xor ecx, EFLAGS_ID ; flip bit 21
push ecx ; set flipped value in EFLAGS
popfd
pushfd ; read it back again
pop eax
xor eax, ecx ; if new value is what we set
shr eax, 21 ; then these two are the same
and eax, 1 ; isolate bit 21 (in bit 0)
xor eax, 1 ; and flip it
stdRET _BlIsCpuidPresent
stdENDP _BlIsCpuidPresent
page
subttl "GetFeatureBits"
;++
;
; VOID
; BlGetFeatureBits(
; VOID
; )
;
; Routine Description:
;
; Execute the CPUID instruction to get the feature bits supported
; by this processor.
;
; Arguments:
;
; None.
;
; Return Value:
;
; Returns the set of feature bits supported by this processor or
; 0 if this processor does not support the CPUID instruction.
;
;--
cPublicProc _BlGetFeatureBits ,0
stdCall _BlIsCpuidPresent ; Does this processor do CPUID?
test eax, 1
jnz short @f ; Jif yes.
xor eax, eax ; No, return 0.
stdRet _BlGetFeatureBits
@@: mov eax, 1 ; CPUID function 1 gets feature bits.
push ebx ; save ebx
cpuid ; execute
;
; Due to a bug in NT 4, some processors report that they do
; not support cmpxchg8b even though they do. Win2K doesn't
; care but cmpxchg8b is a requirement for Whistler.
;
; Check to see if this is one of those processors and if we
; have been told by the processor manufacturer how to reenable
; cmpxchg8b, do so.
;
test edx, 0100h ; is cmpxchg8b present?
jnz short gfb90 ; yes, skip
;
; cmpxchg8b not present, check for recognized processor
;
push eax ; save Family, Model, Stepping
mov eax, 0
cpuid
pop eax
cmp ebx, 0746e6543h ; Cyrix III = 'CentaurHauls'
jnz short gfb30
cmp edx, 048727561h
jnz short gfb80
cmp ecx, 0736c7561h
jnz short gfb80
cmp eax, 0600h ; consider Cyrix III F/M/S 600 and above
;
; Cyrix (Centaur) Set MSR 1107h bit 1 to 1.
;
mov ecx, 01107h
jae gfb20
cmp eax, 0500h ; consider IDT/Centaur F/M/S 500 and above
jb short gfb80
;
; Centaur family 5, set MSR 107h bit 1 to 1.
;
mov ecx, 0107h
gfb20: rdmsr
or eax, 2
wrmsr
jmp short gfb80
gfb30: cmp ebx, 0756e6547h ; Transmeta = 'GenuineTMx86'
jnz short gfb80
cmp edx, 054656e69h
jnz short gfb80
cmp ecx, 03638784dh
jnz short gfb80
cmp eax, 0542h ; consider Transmeta F/M/S 542 and above
jb short gfb80
;
; Transmeta MSR 80860004h is a mask applied to the feature bits.
;
mov ecx, 080860004h
rdmsr
or eax, 0100h
wrmsr
gfb80: mov eax, 1 ; reexecute CPUID function 1
cpuid
gfb90: mov eax, edx ; return feature bits
pop ebx ; restore ebx, esi
stdRET _BlGetFeatureBits
stdENDP _BlGetFeatureBits
_TEXT ends
end