windows-nt/Source/XPSP1/NT/base/mvdm/wow16/win87em/emnew.asm
2020-09-26 16:20:57 +08:00

166 lines
4.1 KiB
NASM

page ,132
subttl emnew - emulator new instruction support
;***
;emnew.asm - emulator new instruction support
;
; Copyright (c) 1985-89, Microsoft Corporation
;
;Purpose:
; Emulator new instruction support
;
; This Module contains Proprietary Information of Microsoft
; Corporation and should be treated as Confidential.
;
;Revision History:
; See emulator.hst
;
;*******************************************************************************
ProfBegin NEW
;*** eFFREE - emulate FFREE ST(i)
;
; ARGUMENTS
; CX = |Op|r/m|MOD|esc|MF|Arith|
; r/m is register to free
;
; DESCRIPTION
; This routine assumes that the register being freed is
; either at the top or the bottom of the floating point
; stack. This is consistent with its use by the cmerge
; compiler. If ST(i) is valid, all registers from ST(0)
; to ST(i-1) are moved down one position in the stack,
; eliminating ST(i). [CURstk] is moved to the new location
; of ST(0).
;
; REGISTERS
; modifies si,di,dx
pub eFFREE
call RegAddr ; di <== address of ST(i)
; carry set if invalid register
jnc short validSTi ; ok, continue
pop edx ; toss return address
jmp InvalidOperand ; set stack underflow/invalid and exit
validSTi:
mov esi,edi ; si <== address of ST(i)
MovLoop:
add esi,Reg87Len ; si <== address of ST(i-1)
cmp esi,[CURstk] ; source addr <= top of stack?
jg short SetCURstk ; set [CURstk] and exit
call MOVRQQ ; ST(j) <== ST(j-1)
add edi,Reg87Len ; move dest ptr to next stack entry
jmp short MovLoop ; continue moving register entries
SetCURstk:
sub edi,Reg87Len ; di points to new location of ST(0)
mov [CURstk],edi ; set new top of stack ptr
ret
;*** eFXCHG - emulate FXCH ST(i)
;
; ARGUMENTS
; CX = |Op|r/m|MOD|esc|MF|Arith|
; r/m is the source register
;
; DESCRIPTION
; exchange ST(i) and ST(0) as follows:
; temp <== ST(0); ST(0) <== ST(i); ST(i) <== temp
; indicate stack underflow error if ST(i) does not exist
;
; REGISTERS
; modifies ax,es,si,di,dx,cx,bx
pub eFXCHG
test cx,01c00h ;test for ST(i) == ST(0)
jz short fxchRet ;fxch ST(0),ST(0) is a nop
mov ax,ds
mov es,ax ;set es == ds
call RegAddr ;di points to ST(i), si points to ST(0)
;carry set if invalid register
jnc short okReg ;ok, continue
pop edx ; toss return address
jmp InvalidOperand ;give stack underflow/invalid error
okReg:
mov ecx,6 ;loop counter
WordSwap: ;exchange a word of ST(0) and ST(i)
mov ax,[esi] ;ax <== [si]
mov bx,[edi] ;bx <== [di]
stos word ptr es:[edi] ;[(di++)] <== ax
mov [esi],bx ;[si] <== bx
inc esi
inc esi ;si++
loop WordSwap ;exchange the six words of ST(0), ST(i)
fxchRet:
ret
;*** eFLDreg - emulate FLD ST(i)
;
; ARGUMENTS
; CX = |Op|r/m|MOD|esc|MF|Arith|
; r/m is the source register
;
; DESCRIPTION
; allocate new ST(0) and copy ST(i) into it
; indicate stack underflow error if ST(i) does not exist
;
; REGISTERS
; modifies ax,di,si
pub eFLDreg
call RegAddr ;di <== address of ST(i), si points to ST(0)
;carry set if invalid register
jnc short okSTi ;yes, continue
pop edx ; toss return address
jmp InvalidOperand ;stack underflow, invalid operation
okSTi:
PUSHST ;allocate new TOS
mov ax,ds
mov es,ax ;set ES == DS
xchg esi,edi ;si = source , di = destination
call MOVRQQ ;move ST(i) to new ST(0)
ret
;*** eFST_Preg - emulate FST ST(i) and FSTP ST(i)
;
; ARGUMENTS
; AX = 0 if FST ST(i)
; 1 if FSTP ST(i)
; CX = |Op|r/m|MOD|esc|MF|Arith|
; (except bit 2 of cl is toggled)
; r/m is the source register
;
; DESCRIPTION
; move contents of ST(0) to ST(i). If ax <> 0 pop stack
; after transfer.
;
; REGISTERS
; modifies si,di,dx
pub eFST_Preg
test cx,01c0h ;test for ST(i) == ST(0)
jz short FSTRet ;pop stack and return
call RegAddr ;di <== address of ST(i), si points to ST(0)
;carry set if invalid register
jnc short ValidReg ;yes, continue
pop edx ; toss return address
jmp InvalidOperand ;no, indicate stack underflow/invalid
ValidReg:
mov dx,ds
mov es,dx ;set es == ds
call MOVRQQ ;ST(i) <== ST(0)
FSTRet:
or ax,ax ;FST ST(i) or FSTP ST(i)?
jz short NoPOP ;FST ST(i) - don't pop the stack
POPST ;pop the 8087 stack
NoPOP:
ret
ProfEnd NEW