summaryrefslogtreecommitdiffstats
path: root/private/ntos/dll/i386/emfmul.asm
blob: 2a5fcca9f54540b9c5c4634abaa94cbf9b2dbb38 (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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
	subttl  emfmul.asm - Multiplication
	page
;*******************************************************************************
;	 Copyright (c) Microsoft Corporation 1991
;	 All Rights Reserved
;
;emfmul.asm - long double multiply
;	by Tim Paterson
;
;Purpose:
;	Long double multiplication.
;Inputs:
;	ebx:esi = op1 mantissa
;	ecx = op1 sign in bit 15, exponent in high half
;	edi = pointer to op2 and result location
;	[Result] = edi
;
;	Exponents are unbiased.  Denormals have been normalized using
;	this expanded exponent range.  Neither operand is allowed to be zero.
;Outputs:
;	Jumps to [RoundMode] to round and store result.
;
;Revision History:
;
; []	09/05/91  TP	Initial 32-bit version.
;
;*******************************************************************************

;Dispatch table for multiply
;
;One operand has been loaded into ecx:ebx:esi ("source"), the other is
;pointed to by edi ("dest").  
;
;Tag of source is shifted.  Tag values are as follows:

.erre	TAG_SNGL	eq	0	;SINGLE: low 32 bits are zero
.erre	TAG_VALID	eq	1
.erre	TAG_ZERO	eq	2
.erre	TAG_SPCL	eq	3	;NAN, Infinity, Denormal, Empty

;Any special case routines not found in this file are in emarith.asm

tFmulDisp	label	dword		;Source (reg)	Dest (*[di])
	dd	MulSingle		;single		single
	dd	MulDouble		;single		double
	dd	XorDestSign		;single		zero
	dd	MulSpclDest		;single		special
	dd	MulDouble		;double		single
	dd	MulDouble		;double		double
	dd	XorDestSign		;double		zero
	dd	MulSpclDest		;double		special
	dd	XorSourceSign		;zero		single
	dd	XorSourceSign		;zero		double
	dd	XorDestSign		;zero		zero
	dd	MulSpclDest		;zero		special
	dd	MulSpclSource		;special	single
	dd	MulSpclSource		;special	double
	dd	MulSpclSource		;special	zero
	dd	TwoOpBothSpcl		;special	special
	dd	XorDestSign		;Two infinities


EM_ENTRY eFIMUL16
eFIMUL16:
	push	offset MulSetResult
	jmp	Load16Int			;Returns to MulSetResult

EM_ENTRY eFIMUL32
eFIMUL32:
	push	offset MulSetResult
	jmp	Load32Int			;Returns to MulSetResult

EM_ENTRY eFMUL32
eFMUL32:
	push	offset MulSetResult
	jmp	Load32Real			;Returns to MulSetResult

EM_ENTRY eFMUL64
eFMUL64:
	push	offset MulSetResult
	jmp	Load64Real			;Returns to MulSetResult

EM_ENTRY eFMULPreg
eFMULPreg:
	push	offset PopWhenDone

EM_ENTRY eFMULreg
eFMULreg:
	xchg	esi,edi

EM_ENTRY eFMULtop
eFMULtop:
	mov	ecx,EMSEG:[esi].ExpSgn
	mov	ebx,EMSEG:[esi].lManHi
	mov	esi,EMSEG:[esi].lManLo
MulSetResult:
	mov     ebp,offset tFmulDisp
	mov	EMSEG:[Result],edi		;Save result pointer
	mov	al,cl
	or	al,EMSEG:[edi].bTag
	cmp	al,bTAG_VALID
.erre	bTAG_VALID	eq	1
.erre	bTAG_SNGL	eq	0
	jz	MulDouble
	ja	TwoOpResultSet
;.erre	MulSingle eq $			;Fall into MulSingle


;*********
MulSingle:
;*********

	mov	edx,EMSEG:[edi].ExpSgn
	mov	eax,EMSEG:[edi].lManHi

;op1 mantissa in ebx:esi, exponent in high ecx, sign in ch bit 7
;op2 high mantissa in eax, exponent in high edx, sign in dh bit 7

	xor	ch,dh			;Compute result sign
	xor	dx,dx			;Clear out sign and tag
	add	ecx,edx			;Result exponent
.erre	TexpBias eq 0			;Exponents not biased
	jo	SMulBigUnderflow	;Multiplying two denormals
ContSmul:

;Value in ecx is correct exponent if result is not normalized.
;If result comes out normalized, 1 will be added.

	mul	ebx			;Compute product
	mov	ebx,edx
	mov	esi,eax
	xor	eax,eax			;Extend with zero

;Result in ebx:esi:eax
;ecx = exponent minus one in high half, sign in ch
	or	ebx,ebx			;Check for normalization
	jns	ShiftOneBit		;In emfadd.asm
	add	ecx,1 shl 16		;Adjust exponent
	jmp	EMSEG:[RoundMode]

SMulBigUnderflow:
	or	EMSEG:[CURerr],Underflow
	add	ecx,Underbias shl 16	;Fix up exponent
	test	EMSEG:[CWmask],Underflow	;Is exception masked?
	jz	ContSmul		;No, continue with multiply
UnderflowZero:
	or	EMSEG:[CURerr],Precision
SignedZero:
	and	ecx,bSign shl 8		;Preserve sign bit
	xor	ebx,ebx
	mov	esi,ebx
	mov	cl,bTAG_ZERO
	jmp	EMSEG:[ZeroVector]

;*******************************************************************************

DMulBigUnderflow:
;Overflow flag set could only occur with denormals (true exp < -32768)
	or	EMSEG:[CURerr],Underflow
	test	EMSEG:[CWmask],Underflow	;Is exception masked?
	jnz	UnderflowZero		;Yes, return zero
	add	ecx,Underbias shl 16	;Fix up exponent
	jmp	ContDmul		;Continue with multiply

PolyMulToZero:
	ret				;Return the zero in registers

PolyMulDouble:
;This entry point is used by polynomial evaluator.
;It checks the operand in registers for zero.
	cmp	cl,bTAG_ZERO		;Adding to zero?
	jz	PolyMulToZero

;*********
MulDouble:
;*********

	mov	eax,EMSEG:[edi].ExpSgn
	mov	edx,EMSEG:[edi].lManHi
	mov	edi,EMSEG:[edi].lManLo

MulDoubleReg:				;Entry point used by transcendentals
;op1 mantissa in ebx:esi, exponent in high ecx, sign in ch bit 7
;op2 mantissa in edx:edi, exponent in high eax, sign in ah bit 7

	xor	ch,ah			;Compute result sign
	xor	ax,ax			;Clear out sign and tag
	add	ecx,eax			;Result exponent
.erre	TexpBias eq 0			;Exponents not biased
	jo	DMulBigUnderflow	;Multiplying two denormals
ContDmul:

;Value in ecx is correct exponent if result is not normalized.
;If result comes out normalized, 1 will be added.

	mov	ebp,edx			;edx is used by MUL instruction

;Generate and sum partial products, from least to most significant

	mov	eax,edi
	mul	esi			;Lowest partial product
	add	eax,-1			;CY set IFF eax<>0
	sbb	cl,cl			;Sticky bit: 0 if zero, -1 if nz
	xchg	edi,edx			;Save high result

;First product: cl reflects low dword non-zero (sticky bit), edi has high dword

	mov	eax,ebx
	mul	edx
	add	edi,eax
	adc	edx,0			;Sum first results
	xchg	edx,esi			;High result to esi

;Second product: accumulated in esi:edi:cl

	mov	eax,ebp			;Next mult. to eax
	mul	edx
	add	edi,eax			;Sum low results
	adc	esi,edx			;Sum high results
	mov	eax,ebx
	mov	ebx,0			;Preserve CY flag
	adc	ebx,ebx			;Keep carry out of high sum

;Third product: accumulated in ebx:esi:edi:cl

	mul	ebp
	add	esi,eax
	adc	ebx,edx
	mov	eax,edi
	or	al,cl			;Collapse sticky bits into eax

;Result in ebx:esi:eax
;ecx = exponent minus one in high half, sign in ch
MulDivNorm:
	or	ebx,ebx			;Check for normalization
	jns	ShiftOneBit		;In emfadd.asm
	add	ecx,1 shl 16		;Adjust exponent
	jmp	EMSEG:[RoundMode]