summaryrefslogtreecommitdiffstats
path: root/private/mvdm/wow16/win87em/emnew.asm
blob: 79eb199a982c0f0744f33ed82aea38bf8324911a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
	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