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
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
|
subttl emload.asm - FLD and FILD instructions
page
;*******************************************************************************
;emload.asm - FLD and FILD instructions
;
; Microsoft Confidential
;
; Copyright (c) Microsoft Corporation 1991
; All Rights Reserved
;
;Purpose:
; FLD and FILD instructions
;Inputs:
; edi = [CURstk]
; dseg:esi = pointer to memory operand
;
;Revision History:
;
; [] 09/05/91 TP Initial 32-bit version.
;
;*******************************************************************************
PrevStackWrap edi,LdStk ;Tied to PrevStackElem below
;*******
EM_ENTRY eFLDreg
eFLDreg:
;*******
; edi = [CURstk]
; esi = pointer to st(i) from instruction field
PrevStackElem edi,LdStk ;Point to receiving location
cmp EMSEG:[edi].bTag,bTAG_EMPTY ;Is it empty?
jnz FldErr
mov ecx,EMSEG:[esi].ExpSgn
cmp cl,bTAG_EMPTY
jz FldErr
mov ebx,EMSEG:[esi].lManHi
mov esi,EMSEG:[esi].lManLo
mov EMSEG:[CURstk],edi
mov EMSEG:[edi].lManLo,esi
mov EMSEG:[edi].lManHi,ebx
mov EMSEG:[edi].ExpSgn,ecx
ret
;This is common code that stores a value into the stack after being loaded
;into registers by the appropriate routine.
PrevStackWrap edi,Load ;Tied to PrevStackElem below
FldCont:
;mantissa in ebx:esi, exp/sign in ecx
;edi = [CURstk]
PrevStackElem edi,Load ;Point to receiving location
cmp EMSEG:[edi].bTag,bTAG_EMPTY ;Is it empty?
jnz FldErr
cmp cl,bTAG_NAN ;Returning a NAN?
jz FldNAN
SaveStack:
mov EMSEG:[CURstk],edi
mov EMSEG:[edi].lManLo,esi
mov EMSEG:[edi].lManHi,ebx
mov EMSEG:[edi].ExpSgn,ecx
ret
FldErr:
or EMSEG:[SWcc],C1 ;Signal overflow
mov EMSEG:[CURerr],StackFlag;Kills possible denormal exception
Unsupported:
call ReturnIndefinite ;in emarith.asm
jz FldExit ;Unmasked, do nothing
mov EMSEG:[CURstk],edi ;Update top of stack
FldExit:
ret
FldNAN:
;Is it a signaling NAN?
test ebx,1 shl 30 ;Check for SNAN
jnz SaveStack ;If QNAN, just use it as result
or EMSEG:[CURerr],Invalid ;Flag the error
or ebx,1 shl 30 ;Make it into a QNAN
test EMSEG:[CWmask],Invalid ;Is it masked?
jnz SaveStack ;If so, update with masked response
ret
;****************
;Load Single Real
;****************
EM_ENTRY eFLD32
eFLD32:
push offset FldCont ;Return address
;Fall into Load32Real
Load32Real:
;dseg:esi points to IEEE 32-bit real number
;On exit:
; mantissa in ebx:esi, exponent in high ecx, sign in ch bit 7, tag in cl
;preserves edi.
mov EMSEG:[PrevDataOff],esi ;Save operand pointer
mov ecx,dseg:[esi] ;Get number
mov ebx,ecx ;Save copy of mantissa
shl ebx,8 ;Normalize
shr ecx,7 ;Bring exponent down
and ecx,0FFH shl 16 ;Look at just exponent
mov ch,dseg:[esi+3] ;Get sign again
jz short ZeroOrDenorm32 ;Exponent is zero
xor esi,esi ;Zero out the low bits
or ebx,1 shl 31 ;Set implied bit
cmp ecx,SexpMax shl 16
jge NANorInf ;Max exp., must be NAN or Infinity
add ecx,(TexpBias-SexpBias) shl 16 ;Change to extended format bias
mov cl,bTAG_SNGL
ret
ZeroOrDenorm32:
;Exponent is zero. Number is either zero or denormalized
xor esi,esi ;Zero out the low bits
and ebx,not (1 shl 31) ;Keep just mantissa
jnz Norm32
mov cl,bTAG_ZERO
ret
Norm32:
add ecx,(TexpBias-SexpBias+1-31) shl 16 ;Fix up bias
jmp FixDenorm
NANorInf:
;Shared by single and double real
and ecx,bSign shl 8 ;Save only sign in ch
or ecx,TexpMax shl 16 + bTAG_NAN ;Max exp.
cmp ebx,1 shl 31 ;Only 1 bit set means infinity
jnz @F
or esi,esi
jnz @F
mov cl,bTAG_INF
@@:
ret
;****************
;Load Double Real
;****************
EM_ENTRY eFLD64
eFLD64:
push offset FldCont ;Return address
;Fall into Load64Real
Load64Real:
;dseg:esi points to IEEE 64-bit real number
;On exit:
; mantissa in ebx:esi, exponent in high ecx, sign in ch bit 7, tag in cl
;preserves edi.
mov EMSEG:[PrevDataOff],esi ;Save operand pointer
mov ecx,dseg:[esi+4] ;Get sign, exp., and high mantissa
mov ebx,ecx ;Save copy of mantissa
shr ecx,4 ;Bring exponent down
and ecx,7FFH shl 16 ;Look at just exponent
mov ch,dseg:[esi+7] ;Get sign again
mov esi,dseg:[esi] ;Get low 32 bits of op
jz short ZeroOrDenorm64 ;Exponent is zero
shld ebx,esi,31-20
shl esi,31-20 ;Normalize
or ebx,1 shl 31 ;Set implied bit
cmp ecx,DexpMax shl 16
jge NANorInf ;Max exp., must be NAN or Infinity
add ecx,(TexpBias-DexpBias) shl 16 ;Change to extended format bias
SetNormTag:
or esi,esi ;Any bits in low half?
.erre bTAG_VALID eq 1
.erre bTAG_SNGL eq 0
setnz cl ;if low half==0 then cl=0 else cl=1
ret
ZeroOrDenorm64:
;Exponent is zero. Number is either zero or denormalized
and ebx,0FFFFFH ;Keep just mantissa
jnz ShortNorm64 ;Are top 20 bits zero?
or esi,esi ;Are low 32 bits zero too?
jnz LongNorm64
mov cl,bTAG_ZERO
ret
LongNorm64:
xchg ebx,esi ;Shift up 32 bits
sub ecx,32 shl 16 ;Correct exponent
ShortNorm64:
add ecx,(TexpBias-DexpBias+12-31) shl 16 ;Fix up bias
FixDenorm:
or EMSEG:[CURerr],Denormal ;Set Denormal Exception
bsr edx,ebx ;Scan for MSB
;Bit number in edx ranges from 0 to 31
mov cl,dl
not cl ;Convert bit number to shift count
shld ebx,esi,cl
shl esi,cl
shl edx,16 ;Move exp. adjustment to high end
add ecx,edx ;Adjust exponent
jmp SetNormTag
;******************
;Load Short Integer
;******************
EM_ENTRY eFILD16
eFILD16:
push offset FldCont ;Return address
;Fall into Load16Int
Load16Int:
;dseg:esi points to 16-bit integer
;On exit:
; mantissa in ebx:esi, exponent in high ecx, sign in ch bit 7, tag in cl
;preserves edi.
mov EMSEG:[PrevDataOff],esi ;Save operand pointer
mov ax,dseg:[esi]
NormInt16:
xor esi,esi ;Extend with zero
cwd ;extend sign through dx
xor ax,dx
sub ax,dx ;Take ABS() of integer
bsr cx,ax ;Find MSB
jz ZeroInt
;Bit number in cx ranges from 0 to 15
not ecx ;Convert to shift count
shl eax,cl ;Normalize
not ecx
.erre TexpBias eq 0
shl ecx,16 ;Move exponent to high half
mov ch,dh ;Set sign
mov ebx,eax ;Mantissa to ebx
mov cl,bTAG_SNGL
ret
ZeroInt:
xor ebx,ebx
mov ecx,ebx
mov cl,bTAG_ZERO
ret
;******************
;Load Long Integer
;******************
EM_ENTRY eFILD32
eFILD32:
push offset FldCont ;Return address
;Fall into Load32Int
Load32Int:
;dseg:esi points to 32-bit integer
;On exit:
; mantissa in ebx:esi, exponent in high ecx, sign in ch bit 7, tag in cl
;preserves edi.
mov EMSEG:[PrevDataOff],esi ;Save operand pointer
mov eax,dseg:[esi]
xor esi,esi ;Extend with zero
or eax,eax ;It it zero?
jz ZeroInt
cdq ;extend sign through edx
xor eax,edx
sub eax,edx ;Take ABS() of integer
mov ebx,eax ;Mantissa to ebx
;BSR uses 3 clocks/bit, so speed it up by checking the top half
;This saves 36 clocks on 386 (42 on 486sx)
;Cost is 13 clocks on 386 if high word isn't zero (5 on 486sx)
.erre TexpBias eq 0
xor eax,eax ;Initialize exponent
cmp ebx,0FFFFH ;Upper bits zero?
ja @F
shl ebx,16
sub eax,16
@@:
bsr ecx,ebx ;Find MSB
add eax,ecx ;Compute expoment
not cl ;Convert bit number to shift count
shl ebx,cl ;Normalize
shrd ecx,eax,16 ;Move exponent to high half of ecx
mov ch,dh ;Set sign
mov cl,bTAG_SNGL
ret
;*****************
;Load Quad Integer
;*****************
EM_ENTRY eFILD64
eFILD64:
mov EMSEG:[PrevDataOff],esi ;Save operand pointer
mov ebx,dseg:[esi+4] ;Get high 32 bits
mov eax,ebx ;Make copy of sign
mov esi,dseg:[esi] ;Get low 32 bits
mov ecx,ebx
or ecx,esi ;Is it zero?
jz ZeroQuad
NormQuadInt:
;Entry point from eFBLD
;eax bit 31 = sign
;ebx:esi = integer
;edi = [CURstk]
.erre TexpBias eq 0
mov ax,32 ;Initialize exponent
or ebx,ebx ;Check sign
jz LongNormInt
jns FindBit
not ebx
neg esi ;CY set if non-zero
sbb ebx,-1 ;Add one if esi == 0
jnz FindBit ;Check for high bits zero
LongNormInt:
xchg ebx,esi ;Normalize 32 bits
xor ax,ax ;Reduce exponent by 32
FindBit:
;BSR uses 3 clocks/bit, so speed it up by checking the top half
;This saves 35 clocks on 386 (41 on 486sx)
;Cost is 11 clocks on 386 if high word isn't zero (4 on 486sx)
cmp ebx,0FFFFH ;Upper bits zero?
ja @F
shld ebx,esi,16
shl esi,16
sub eax,16
@@:
bsr ecx,ebx ;Find MSB
add eax,ecx ;Compute expoment
not cl ;Convert bit number to shift count
shld ebx,esi,cl ;Normalize
shl esi,cl
mov ecx,eax ;Move sign and exponent to ecx
rol ecx,16 ;Swap sign and exponent halves
or esi,esi ;Any bits in low half?
.erre bTAG_VALID eq 1
.erre bTAG_SNGL eq 0
setnz cl ;if low half==0 then cl=0 else cl=1
jmp FldCont
ZeroQuad:
mov cl,bTAG_ZERO
jmp FldCont
;****************
;Load Temp Real
;****************
PrevStackWrap edi,Ld80 ;Tied to PrevStackElem below
EM_ENTRY eFLD80
eFLD80:
;This is not considered an "arithmetic" operation (like all the others are),
;so SNANs do NOT cause an exception. However, unsupported formats do.
mov EMSEG:[PrevDataOff],esi ;Save operand pointer
PrevStackElem edi,Ld80 ;Point to receiving location
cmp EMSEG:[edi].bTag,bTAG_EMPTY ;Is it empty?
jnz FldErr
LoadTempReal:
mov ebx,dseg:[esi+4] ;Get high half of mantissa
mov cx,dseg:[esi+8] ;Get exponent and sign
mov esi,dseg:[esi] ;Get low half of mantissa
mov eax,ecx
and ch,7FH ;Mask off sign bit
shl ecx,16 ;Move exponent to high end
mov ch,ah ;Restore sign
jz ZeroOrDenorm80
;Check for unsupported format: unnormals (MSB not set)
or ebx,ebx
jns Unsupported
sub ecx,(IexpBias-TexpBias) shl 16 ;Correct the bias
cmp ecx,TexpMax shl 16
jge NANorInf80
SetupTag:
or esi,esi ;Any bits in low half?
.erre bTAG_VALID eq 1
.erre bTAG_SNGL eq 0
setnz cl ;if low half==0 then cl=0 else cl=1
jmp SaveStack
NANorInf80:
mov cl,bTAG_NAN
cmp ebx,1 shl 31 ;Only 1 bit set means infinity
jnz SaveStack
or esi,esi
jnz SaveStack
mov cl,bTAG_INF
jmp SaveStack
ZeroOrDenorm80:
;Exponent is zero. Number is either zero or denormalized
or ebx,ebx
jnz ShortNorm80 ;Are top 32 bits zero?
or esi,esi ;Are low 32 bits zero too?
jnz LongNorm80
mov cl,bTAG_ZERO
jmp SaveStack
;This code accepts and works correctly with pseudo-denormals (MSB already set)
LongNorm80:
xchg ebx,esi ;Shift up 32 bits
sub ecx,32 shl 16 ;Correct exponent
ShortNorm80:
add ecx,(TexpBias-IexpBias+1-31) shl 16 ;Fix up bias
bsr edx,ebx ;Scan for MSB
;Bit number in edx ranges from 0 to 31
mov cl,dl
not cl ;Convert bit number to shift count
shld ebx,esi,cl
shl esi,cl
shl edx,16 ;Move exp. adjustment to high end
add ecx,edx ;Adjust exponent
jmp SetUpTag
|