193 lines
4.6 KiB
NASM
193 lines
4.6 KiB
NASM
|
page ,132
|
||
|
subttl emspec.asm - Special emulator functions for speed
|
||
|
;***
|
||
|
;emspec.asm - Special emulator functions for speed
|
||
|
;
|
||
|
; Copyright (c) 1987-89, Microsoft Corporation
|
||
|
;
|
||
|
;Purpose:
|
||
|
; Special emulator functions for speed
|
||
|
;
|
||
|
; This Module contains Proprietary Information of Microsoft
|
||
|
; Corporation and should be treated as Confidential.
|
||
|
;
|
||
|
;Revision History:
|
||
|
; See emulator.hst
|
||
|
;
|
||
|
;*******************************************************************************
|
||
|
|
||
|
|
||
|
ProfBegin SPEC
|
||
|
|
||
|
|
||
|
pub loadcontrolword
|
||
|
ifdef QB3
|
||
|
or al,2 ; mask denormal exceptions
|
||
|
endif ;QB3
|
||
|
mov [UserControlWord],ax ; save user's version
|
||
|
and ax,0FF3CH ; Turn off reserved, IEM, Denormal
|
||
|
; & invalid exception mask bits
|
||
|
ifndef frontend
|
||
|
ifndef only87
|
||
|
cmp [Have8087],0 ; Non-0 if 8087 present
|
||
|
je EmulateFLDCW
|
||
|
endif ;only87
|
||
|
|
||
|
mov [REMLSW],ax ; use this cell (not busy)
|
||
|
fnop ; fix for intel erratum #8
|
||
|
fldcw [REMLSW] ; 8087 gets new control word
|
||
|
endif ;frontend
|
||
|
|
||
|
pub EmulateFLDCW
|
||
|
mov [ControlWord],ax ; save internal control word
|
||
|
ret
|
||
|
|
||
|
|
||
|
;-----------------------------------------------------------------------------
|
||
|
|
||
|
ifndef QB3 ; rest not needed if QB 3
|
||
|
|
||
|
pub storecontrolword
|
||
|
mov ax,[UserControlWord] ; get user's version
|
||
|
ret
|
||
|
|
||
|
|
||
|
pub storestatusword
|
||
|
xor ax,ax
|
||
|
ifndef frontend
|
||
|
cmp al,[Have8087]
|
||
|
je no87status
|
||
|
fstsw [NewStatusWord]
|
||
|
fwait
|
||
|
mov al,byte ptr [NewStatusWord] ; get exception summary
|
||
|
and al,03Fh ; only low 6 bits are wanted
|
||
|
endif ;frontend
|
||
|
|
||
|
pub no87status
|
||
|
or ax,[UserStatusWord] ; or with full status
|
||
|
and ax,UStatMask ; mask down to actual status bits
|
||
|
mov [UserStatusWord],ax ; update full status word
|
||
|
ret
|
||
|
|
||
|
page
|
||
|
|
||
|
; Procedure to truncate TOS to integer TOS
|
||
|
|
||
|
; ax = new rounding control
|
||
|
|
||
|
pub truncateTOS
|
||
|
and ax,RoundControl shl 8 ; mask to new rounding control
|
||
|
|
||
|
ifndef frontend
|
||
|
ifndef only87
|
||
|
cmp [Have8087],0
|
||
|
je Emulatetruncate
|
||
|
endif ;only87
|
||
|
|
||
|
FSTCW [ControlWord] ; get control word
|
||
|
FWAIT ; synchronize
|
||
|
MOV CX,[ControlWord] ; round mode saved
|
||
|
and ch,not RoundControl ; clear rounding control bits
|
||
|
OR ax,cx ; set new rounding
|
||
|
MOV [REMLSW],AX ; back to memory
|
||
|
FLDCW [REMLSW] ; reset rounding
|
||
|
FRNDINT ; "round" top of stack
|
||
|
FLDCW [ControlWord] ; restore rounding
|
||
|
RET ; simple return
|
||
|
endif ;frontend
|
||
|
|
||
|
ifndef only87
|
||
|
pub Emulatetruncate
|
||
|
mov cx,[ControlWord]
|
||
|
push cx ; remember what control word was
|
||
|
and ch,not RoundControl ; clear rounding control bits
|
||
|
OR ah,ch ; set new rounding
|
||
|
MOV [CWcntl],ah ; flag new rounding mode
|
||
|
PUSH BP ; save BP
|
||
|
CALL eFRNDINT
|
||
|
POP BP ; restore BP
|
||
|
POP [ControlWord] ; set back to the way it was
|
||
|
|
||
|
call checktrunc ; check for truncation error
|
||
|
|
||
|
RET ; finished
|
||
|
endif ;only87
|
||
|
|
||
|
page
|
||
|
|
||
|
; Procedure to truncate TOS to integer in DX:AX
|
||
|
|
||
|
; ax = new rounding control
|
||
|
|
||
|
pub truncateTOSto32int
|
||
|
and ax,RoundControl shl 8
|
||
|
|
||
|
ifndef frontend
|
||
|
ifndef only87
|
||
|
cmp [Have8087],0
|
||
|
je Emulatetruncateto32int
|
||
|
endif ;only87
|
||
|
|
||
|
FSTCW [ControlWord] ; get control word
|
||
|
FWAIT ; synchronize
|
||
|
MOV CX,[ControlWord] ; round mode saved
|
||
|
and ch,not RoundControl ; clear rounding control bits
|
||
|
OR ax,cx ; set new rounding
|
||
|
MOV [REMLSW],AX ; back to memory
|
||
|
FLDCW [REMLSW] ; reset rounding
|
||
|
FISTP dword ptr [REMLSW] ; "round" top of stack
|
||
|
FLDCW [ControlWord] ; restore rounding
|
||
|
mov ax,[REMLSW]
|
||
|
mov dx,[REMLSW+2]
|
||
|
RET ; simple return
|
||
|
endif ;frontend
|
||
|
|
||
|
ifndef only87
|
||
|
pub Emulatetruncateto32int
|
||
|
mov cx,[ControlWord]
|
||
|
push cx ; remember what control word was
|
||
|
and ch,not RoundControl ; clear rounding control bits
|
||
|
OR ah,ch ; set new rounding
|
||
|
MOV [CWcntl],ah ; flag new rounding mode
|
||
|
PUSH BP ; save BP
|
||
|
CALL TOSto32int ; convert to 32-bit int in BX:DX
|
||
|
POP BP ; restore BP
|
||
|
mov ax,dx
|
||
|
mov dx,bx
|
||
|
|
||
|
call checktrunc ; check for truncation error
|
||
|
|
||
|
POPST ; pop of current stack entry
|
||
|
POP [ControlWord] ; set back to the way it was
|
||
|
|
||
|
pub truncerrOK ; (reuse RET for routine below)
|
||
|
RET ; finished
|
||
|
|
||
|
; check for errors
|
||
|
|
||
|
pub checktrunc ; !!! check emmain for same code
|
||
|
MOV cx,[CURerr] ; fetch errors
|
||
|
or [UserStatusWord],cx ; OR into user status word
|
||
|
OR [SWerr],cl ; set errors in sticky error flag
|
||
|
NOT cl ; make a zero mean an error
|
||
|
MOV ch,byte ptr [UserControlWord] ; get user's IEEE control word
|
||
|
OR ch,0C2H ; mask reserved, IEM and denormal bits
|
||
|
AND ch,03FH ; unmask invalid instruction,
|
||
|
; stack overflow.
|
||
|
OR cl,ch ; mask for IEEE exceptions
|
||
|
NOT cl ; make a one mean an error
|
||
|
MOV ch,byte ptr (CURerr+1) ; get stack over/underflow flags
|
||
|
TEST cx,0FFFFh-MemoryOperand ; test for errors to report
|
||
|
jz truncerrOK ; error is masked
|
||
|
|
||
|
xchg ax,cx ; ax = exception
|
||
|
jmp CommonExceptions ; handle error (??? unclean stack)
|
||
|
|
||
|
endif ;only87
|
||
|
|
||
|
|
||
|
endif ;QB3
|
||
|
|
||
|
|
||
|
ProfEnd SPEC
|