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

371 lines
9.2 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

SETUP equ 1
;**
;
; Machine-specific detection code
;
;--
.386p
include hal386.inc
include callconv.inc
;
; Include SystemPro detection code
;
SYSTEMPRO equ 1
include halsp\i386\spdetect.asm
_TEXT SEGMENT DWORD PUBLIC 'CODE'
ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
;
; Thunk functions.
; Equivalent Hal functions which various detection code may use
;
;++
;
; CMOS space read functions.
;
;--
CMOSAddressPort equ 70H
CMOSDataPort equ 71H
CMOSExAddressLSBPort equ 74H
CMOSExAddressMSBPort equ 75H
CMOSExDataPort equ 76H
;++
;
; VOID
; ReadCMOS(
; ULONG StartingOffset
; ULONG Count
; PUCHAR ReturnValuePtr
; )
;
; Read CMOS starting at the given offset for the given number of
; bytes putting the bytes read into the buffer pointed to by the
; given address.
;
; Arguments:
;
; StartingOffset : where to start in CMOS
;
; Count : how many bytes to read
;
; ReturnValuePtr : where to put bytes read
;
; Returns:
; None.
;
;--
StartingOffset equ 2*4[ebp]
Count equ 3*4[ebp]
ReturnValuePtr equ 4*4[ebp]
cPublicProc _ReadCMOS,3
push ebp
mov ebp, esp
push ebx ; caller's reg
push edi ; caller's reg
mov ebx, StartingOffset
mov ecx, Count
mov edi, ReturnValuePtr
align dword
NextByte:
cmp bh, 0
jne ExCMOSRead
mov al, bl
out CMOSAddressPort, al
in al, CMOSDataPort
mov [edi], al
add ebx, 1
add edi, 1
sub ecx, 1
jg NextByte
pop edi ; restore caller's reg
pop ebx ; restore caller's reg
pop ebp
stdRET _ReadCmos
align dword
ExCMOSRead:
mov al, bl
out CMOSExAddressLSBPort, al
mov al, bh
out CMOSExAddressMSBPort, al
in al, CMOSExDataPort
mov [edi], al
add ebx, 1
add edi, 1
sub ecx, 1
jg ExCMOSRead
pop edi ; restore caller's reg
pop ebx ; restore caller's reg
pop ebp
stdRET _ReadCMOS
stdENDP _ReadCMOS
; 486 C step CPU detection code.
CR0_ET equ 10h
CR0_TS equ 08H
CR0_EM equ 04H
CR0_MP equ 02H
;
; The following equates define the control bits of EFALGS register
;
EFLAGS_AC equ 40000h
EFLAGS_ID equ 200000h
;
; Constants for Floating Point test
;
REALLONG_LOW equ 00000000
REALLONG_HIGH equ 3FE00000h
PSEUDO_DENORMAL_LOW equ 00000000h
PSEUDO_DENORMAL_MID equ 80000000h
PSEUDO_DENORMAL_HIGH equ 0000h
;
; Define the iret frame
;
IretFrame struc
IretEip dd 0
IretCs dd 0
IretEFlags dd 0
IretFrame ends
;++
;
; BOOLEAN
; Detect486CStep (
; IN PBOOLEAN Dummy
; )
;
; Routine Description:
;
; Returns TRUE if the processor is a 486 C stepping. We detect the CPU
; in order to use a specific HAL. This HAL attempts to work around
; a 486 C stepping bug which the normal HAL tends to aggravate.
;
cPublicProc _Detect486CStep,1
push edi
push esi
push ebx ; Save C registers
mov eax, cr0
push eax
pushfd ; save Cr0 & flags
pop ebx ; Get flags into eax
push ebx ; Save original flags
mov ecx, ebx
xor ecx, EFLAGS_AC ; flip AC bit
push ecx
popfd ; load it into flags
pushfd ; re-save flags
pop ecx ; get flags into eax
cmp ebx, ecx ; did bit stay flipped?
je short Not486C ; No, then this is a 386
mov ecx, ebx
xor ecx, EFLAGS_ID ; flip ID bit
push ecx
popfd ; load it into flags
pushfd ; re-save flags
pop ecx ; get flags into eax
cmp ebx, ecx ; did bit stay flipped?
jne short Not486C ; Yes, then this >= 586
mov eax, cr0
and eax, NOT (CR0_ET+CR0_MP+CR0_TS+CR0_EM)
mov cr0, eax
call IsNpxPresent ; Check if cpu has coprocessor support?
or ax, ax
jz short Is486C ; it is actually 486sx, assume C step
call Check486CStepping ; Check for <= C stepping
jnc short Not486C ; if nc, it is NOT a C stepping
Is486C:
mov eax, 1 ; Return TRUE
jmp short DetectCpuExit
Not486C:
xor eax, eax
DetectCpuExit:
popfd
pop ebx
mov cr0, ebx
pop ebx
pop esi
pop edi
stdRET _Detect486CStep
stdENDP _Detect486CStep
;++
;
; BOOLEAN
; Check486CStepping (
; VOID
; )
;
; Routine Description:
;
; This routine checks for 486 C Stepping.
;
; This routine takes advantage of the fact that FSCALE produces
; wrong result with Denormal or Pseudo-denormal operand on 486
; C and earlier steps.
;
; If the value contained in ST(1), second location in the floating
; point stack, is between 1 and 11, and the value in ST, top of the
; floating point stack, is either a pseudo-denormal number or a
; denormal number with the underflow exception unmasked, the FSCALE
; instruction produces an incorrect result.
;
; Arguments:
;
; None.
;
; Return Value:
;
; Carry Flag clear if D or later stepping.
; Carry Flag set if C stepping.
;
;--
FpControl equ [ebp - 2]
RealLongSt1 equ [ebp - 10]
PseudoDenormal equ [ebp - 20]
FscaleResult equ [ebp - 30]
public Check486CStepping
Check486CStepping proc
push ebp
mov ebp, esp
sub esp, 30 ; Allocate space for temp real variables
;
; Initialize the local FP variables to predefined values.
; RealLongSt1 = 1.0 * (2 ** -1) = 0.5 in normalized double precision FP form
; PseudoDenormal = a unsupported format by IEEE.
; Sign bit = 0
; Exponent = 000000000000000B
; Significand = 100000...0B
; FscaleResult = The result of FSCALE instruction. Depending on 486 step,
; the value will be different:
; Under C and earlier steps, 486 returns the original value
; in ST as the result. The correct returned value should be
; original significand and an exponent of 0...01.
;
mov dword ptr RealLongSt1, REALLONG_LOW
mov dword ptr RealLongSt1 + 4, REALLONG_HIGH
mov dword ptr PseudoDenormal, PSEUDO_DENORMAL_LOW
mov dword ptr PseudoDenormal + 4, PSEUDO_DENORMAL_MID
mov word ptr PseudoDenormal + 8, PSEUDO_DENORMAL_HIGH
.387
fnstcw FpControl ; Get FP control word
or word ptr FpControl, 0FFh ; Mask all the FP exceptions
fldcw FpControl ; Set FP control
fld qword ptr RealLongSt1 ; 0 < ST(1) = RealLongSt1 < 1
fld tbyte ptr PseudoDenormal; Denormalized operand. Note, i486
; won't report denormal exception
; on 'FLD' instruction.
; ST(0) = Extended Denormalized operand
fscale ; try to trigger 486Cx errata
fstp tbyte ptr FscaleResult ; Store ST(0) in FscaleResult
cmp word ptr FscaleResult + 8, PSEUDO_DENORMAL_HIGH
; Is Exponent changed?
jz short c4ds00 ; if z, no, it is C step
clc
jmp short c4ds10
c4ds00: stc
c4ds10: mov esp, ebp
pop ebp
ret
Check486CStepping endp
;++
;
; BOOLEAN
; IsNpxPresent(
; VOID
; );
;
; Routine Description:
;
; This routine determines if there is any Numeric coprocessor
; present.
;
; Arguments:
;
; None.
;
; Return:
;
; TRUE - If NPX is present. Else a value of FALSE is returned.
;
;--
public IsNpxPresent
IsNpxPresent proc near
push ebp ; Save caller's bp
xor edx, edx
.287
fninit ; Initialize NPX
mov ecx, 5A5A5A5Ah ; Put non-zero value
push ecx ; into the memory we are going to use
mov ebp, esp
fnstsw word ptr [ebp] ; Retrieve status - must use non-wait
cmp byte ptr [ebp], 0 ; All bits cleared by fninit?
jne Inp10
mov edx, 1
Inp10:
pop eax ; clear scratch value
pop ebp ; Restore caller's bp
mov eax, edx
ret
IsNpxPresent endp
_TEXT ENDS
END