summaryrefslogtreecommitdiffstats
path: root/private/ntos/dll/i386/emload.asm
blob: c2e68c5616ec68818711993e8ee53afe5ba0e6af (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
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