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]
|