summaryrefslogblamecommitdiffstats
path: root/private/ntos/inc/em387.inc
blob: 7c30099a8176ed03eb716c0cd9db63f6615e23b8 (plain) (tree)
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
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445




























































































































































































































































































































































































































































                                                                                                                    
        subttl  em387.inc - Emulator Internal Format and Macros
	page
;***
;em387.inc - Emulator Internal Format and Macros
;
;	 Microsoft Confidential
;
;	 Copyright (c) Microsoft Corporation 1987, 1992
;
;	 All Rights Reserved
;
;Purpose:
;	Emulator Internal Format and Macros
;
;Revision History:  (also see emulator.hst)
;
;    8/23/91  TP    New tag definitions
;   10/30/89  WAJ   Added this header.
;   02/12/89  WAJ   Added local stack frame definition.
;
;*******************************************************************************


GetEmData	macro	dest,use
ifdef	_CRUISER
	mov	dest,[edataSEG]
elseifdef  _DOS32EXT
ifdifi	<use>,<ax>
	push	eax
	call	_SelKrnGetEmulData
	mov	dest,ax
	pop	eax
else
	call	_SelKrnGetEmulData
	mov	dest,ax
endif
endif
	endm



;The SKIP macro optimizes very short jumps by treating the code
;as data to a "cmp" instruction.  This reduces jump time from
;8 clocks or more down to 2 clocks.  It destroy the flags!

SKIP	macro	dist,target
if	dist eq 4
	db	3DH			;cmp eax,<immed>
elseif	dist eq 3
	db	3DH,0			;cmp eax,<immed>
elseif	dist eq 2
	db	66H,3DH			;cmp ax,<immed>
elseif	dist eq 1
	db	3CH			;cmp al,<immed>
else
	.err
endif

	ifnb	<target>
.erre	$+dist eq target
	endif

	endm

;*******************************************************************************
;
;   80x87 environment structures.
;
;*******************************************************************************


Env80x87_32 struc
	E32_ControlWord	dw	?
	reserved1		dw	?
	E32_StatusWord	dw	?
	reserved2		dw	?
	E32_TagWord		dw	?
	reserved3		dw	?
	E32_CodeOff		dd	?
	E32_CodeSeg		dw	?
	reserved4		dw	?
	E32_DataOff		dd	?
	E32_DataSeg		dw	?
	reserved5		dw	?
Env80x87_32 ends


;---------------------------------------------------------------------------
;
; Emulator Internal Format:
;
;	     +0  +1  +2  +3  +4  +5  +6  +7  +8  +9  +10 +11
;	    .___.___.___.___.___.___.___.___.___.___.___.___.
;   ptr --> |___|___|___|___|___|___|___|___|___|___|___|___|
;	     lsb			 msb tag sgn exl exh
;	    |<---      mantissa 	--->|       |exponent
;
;   The mantissa contains the leading 1 before the decimal point in the hi
;   bit of the msb. The exponent is not biased (signed two's complement).
;   The flag and tag bytes are as below.
;
;   bit:      7   6   5   4   3   2   1   0
;	    .___.___.___.___.___.___.___.___.
;   Sign:   |___|_X_|_X_|_X_|_X_|_X_|_X_|_X_|  X = unused
;	      ^ 
;     SIGN
;
;
;   bit:      7   6   5   4   3   2   1   0
;	    .___.___.___.___.___.___.___.___.
;   Tag:    |___|___|_X_|_X_|___|___|___|___|  X = unused
;	      ^	  ^	      ^	  ^   ^   ^
;	      |	  |	      |	  |   |	  |
;    387 tag -+---+	      |	  |   |   |
;			      |	  |   |	  |
;    Special enumeration -----+---+   |	  |
;				      |	  |
;    Internal tag --------------------+---+
;
;There are four internal tags: Single, Double, Zero, Special.  Within
;Special, there is NAN, Infinity, Denormal, and Empty.
;
;Representations for Single, Double, and Denormal are the same.  Denormals
;are not actually kept denormalized, although they are rounded to the
;correct number of bits as if they were.  The Single tag means the 
;low 32 bits of the mantissa are zero.  This allows optimizing multiply 
;and divide.
;
;Tag		Mantissa	Exponent	Sign
;---------------------------------------------------
;Zero		0		0		valid
;Empty		?		?		?
;NAN		valid		TexpMax		valid
;Infinity	8000...000	TexpMax		valid
;
;The mantissa for a NAN distinguishes between a quiet NAN (QNAN) or a 
;signaling NAN (SNAN).  If the bit below the MSB is 1, it is a QNAN,
;otherwise it is an SNAN.
;


;*******************************************************************************
;*
;*  Stack entry defineds with a struct.
;*
;*******************************************************************************

EmStackEntry struc
    bMan0   db	    ?
    bMan1   db	    ?
    bMan2   db	    ?
    bMan3   db	    ?
    bMan4   db	    ?
    bMan5   db	    ?
    bMan6   db	    ?
    bMan7   db	    ?
    bTag    db	    ?
    bSgn    db      ?
    bExpLo  db      ?
    bExpHi  db      ?
EmStackEntry ends

wMantisa struc
    wMan0   dw	    ?
    wMan1   dw	    ?
    wMan2   dw	    ?
    wMan3   dw	    ?
    TagSgn  dw	    ?
    wExp    dw	    ?
wMantisa ends


lMantisa struc
    lManLo	dd	?
    lManHi	dd	?
    ExpSgn	dd	?
lMantisa ends

.erre	size lMantisa eq size wMantisa

Reg87Len	equ	size lMantisa


;*******************************************************************************
;*
;*  bFlags and bTag constants.
;*
;*******************************************************************************

;The rules for internal number formats:
;
;1. Everything is either normalized or zero--unnormalized formats cannot
;get in.  So if the high half mantissa is zero, the number must be all zero.
;
;2. Although the exponent bias is different, NANs and Infinities are in
;standard IEEE format - exponent is TexpMax, mantissa indicates NAN vs.
;infinity (mantissa for infinity is 800..000H).
;
;3. Denormals have an exponent less than TexpMin.
;
;4. If the low half of the mantissa is zero, it is tagged bTAG_SNGL
;
;5. Everything else is bTAG_VALID


bSign	    equ     80h

;These are the INTERNAL flags
TAG_MASK	equ	3
TAG_SHIFT	equ	2
;
TAG_SNGL	equ	0		;SINGLE: low 32 bits are zero
TAG_VALID	equ	1
TAG_ZERO	equ	2
TAG_SPCL	equ	3		;NAN, Infinity, Denormal, Empty
ZEROorSPCL      equ     2	       ;Test for Zero or Special
;Enumeration of "special":
TAG_SPCLBITS	equ	0CH
TAG_EMPTY	equ	TAG_SPCL+(0 shl TAG_SHIFT)
TAG_INF		equ	TAG_SPCL+(1 shl TAG_SHIFT)
TAG_NAN		equ	TAG_SPCL+(2 shl TAG_SHIFT)
TAG_DEN		equ	TAG_SPCL+(3 shl TAG_SHIFT)

;These are the tags used by the 387
T87_VALID	equ	0
T87_ZERO	equ	1
T87_SPCL	equ	2		;NAN, Infinity, Denormal
T87_EMPTY	equ	3

;The tag word for each stack entry combines these two tags.
;Internal tags are in the low bits, 387 tags are in the high two bits
bTAG_VALID	equ	(T87_VALID shl 6) or TAG_VALID
bTAG_SNGL	equ	(T87_VALID shl 6) or TAG_SNGL
bTAG_ZERO	equ	(T87_ZERO shl 6) or TAG_ZERO
bTAG_NAN	equ	(T87_SPCL shl 6) or TAG_NAN
bTAG_INF	equ	(T87_SPCL shl 6) or TAG_INF
bTAG_EMPTY	equ	(T87_EMPTY shl 6) or TAG_EMPTY
bTAG_DEN	equ	(T87_SPCL shl 6) or TAG_DEN
bTAG_NOPOP	equ	-1

bTAG_MASK   equ     3



MantissaByteCnt equ	8

IexpBias	equ	3FFFh	; 16,383
IexpMax 	equ	7FFFh	; Biased Exponent for Infinity
IexpMin 	equ	0	; Biased Exponent for zero

DexpBias	equ	3FFh	; 1023
DexpMax 	equ	7FFh	; Biased Exponent for Infinity
DexpMin 	equ	0	; Biased Exponent for zero

SexpBias	equ	07Fh	; 127
SexpMax 	equ	0FFh	; Biased Exponent for Infinity
SexpMin 	equ	0	; Biased Exponent for zero

TexpBias	equ	0	; Bias for internal format of temp real
UnderBias	equ	24576	; 3 * 2^13.  Extra bias for unmasked underflow
TexpMax		equ	IexpMax - IexpBias + TexpBias	;NAN/Infinity exponent
TexpMin		equ	IexpMin-IexpBias+1	;Smallest non-denormal exponent

; Control Word Format	CWcntl

RoundControl		equ	0Ch
    RCchop		equ	0Ch
    RCup		equ	08h
    RCdown		equ	04h
    RCnear		equ	 0

PrecisionControl	equ	03h
    PC24		equ	 0
    PC53		equ	02h
    PC64		equ	03h

; Status Word Format	SWcc
    C0			equ	01h
    C1			equ	02h
    C2			equ	04h
    C3			equ	40h
ConditionCode		equ	C3 or C2 or C1 or C0
    CCgreater		equ	 0
    CCless		EQU	C0
    CCequal		equ	C3
    CCincomprable	equ	C3 or C2 or C0

RoundUp			equ	C1
StackOverflow		equ	C1

; Status Flags Format	CURerr

Invalid 		equ	   1h		; chip status flags
Denormal		equ	   2h
ZeroDivide		equ	   4h
Overflow		equ	   8h
Underflow		equ	  10h
Precision		equ	  20h
StackFlag		equ	  40h
Summary 		equ	  80h

SavedErrs		equ	Invalid or Denormal or ZeroDivide or Overflow or Underflow or Precision or StackFlag
LongSavedFlags	equ	(CCincomprable SHL 16) OR (SavedErrs SHL 8)	; save C0, C2, C3 & errs
;*******************************************************************************
;*
;*  Define emulator interrupt stack frame.
;*
;*******************************************************************************

StackFrame   struc
            regEAX	    dd	    ?
	    regECX	    dd	    ?
	    regEDX	    dd	    ?
	    regEBX	    dd	    ?
	    regESP	    dd	    ?
	    regEBP	    dd	    ?
	    regESI	    dd	    ?
	    regEDI	    dd	    ?
	    OldCodeOff      dd      ?
	    OldLongStatus   dd      ?
	    regDS	    dd	    ?
	    regEIP	    dd	    ?
	    regCS	    dd	    ?
	    regFlg	    dd	    ?
StackFrame  ends

regAX	    equ		    word ptr regEAX

; .erre   StatusWord eq LongStatusWord+1
OldStatus   equ		    word ptr OldLongStatus+1

;*******************************************************************************
;*
;*  Define emulator entry point macro.
;*
;*******************************************************************************

EM_ENTRY	macro	entryname
ifdef NT386
public ___&entryname
___&entryname:
endif			; ifdef NT386
		endm

Em87Busy	EQU	1
Em87Idle	EQU	0



ifdef NT386
;*********************************************************************;
;								      ;
;                     Emulator TEB Layout                             ;
;								      ;
;*********************************************************************;

.errnz (TbSystemReserved1 and 3)        ; Make sure TB is dword aligned

Numlev          equ     8               ; Number of stack registers

InitControlWord	equ	37FH		; Default - Round near,
					; 64 bits, all exceptions masked

DefaultControlWord equ  27FH            ; Default - Round near,
                                        ; 53 bits, all exceptions masked

EmulatorTebData struc
    TbSystemResrvd  db      TbSystemReserved1 DUP (?)   ; Skip to Emulator area

    RoundMode       dd      ?           ; Address of rounding routine
    SavedRoundMode  dd      ?           ; For restoring RoundMode
    ZeroVector      dd      ?           ; Address of sum-to-zero routine
    TransRound      dd      ?           ; Round mode w/o precision
    Result          dd      ?           ; Result pointer
    PrevCodeOff     dd      ?
    PrevDataOff     dd      ?

    ;(See comment below on 'emulator stack area'
    CURstk          dd      ?           ; init to start of stack
    BEGstk          db      (Numlev-1)*Reg87Len dup(?) ;Allocate register 1 - 7
    INITstk         db      Reg87Len dup(?)

    FloatTemp       db      Reg87Len dup(?)
    ArgTemp         db      Reg87Len dup(?)

    Einstall        db      0           ; Emulator installed flag
    SWerr           db      ?           ; Initially no exceptions (sticky flags)
    SWcc            db      ?           ; Condition codes from various operations
    CURerr          db      ?           ; initially 8087 exception flags clear
                                        ; this is the internal flag reset after
                                        ; each operation to detect per instruction
                                        ; errors
    CWmask          db      ?           ; exception masks
    CWcntl          db      ?           ; arithmetic control flags
    ErrMask         db      ?
    dummy           db      ?
EmulatorTebData ends

ENDstk          equ byte ptr INITstk + Reg87Len
LongStatusWord  equ dword ptr Einstall  ;Combine Einstall, CURerr, StatusWord
StatusWord      equ word ptr SWerr      ;Combine SWerr, SWcc
CurErrCond      equ word ptr SWcc       ;Combine SWcc, CURErr
LongControlWord equ dword ptr CWmask    ;Combine CWMask, CWcntl, ErrMask, dummy
ControlWord     equ word ptr CWmask     ;Combine CWMask, CWcntl

YFloatTemp      equ FloatTemp
YArgTemp        equ ArgTemp

.errnz (SWerr   - Einstall -1)
.errnz (SWcc    - Einstall -2)
.errnz (CURerr  - Einstall -3)
.errnz (CWcntl  - CWmask   -1)
.errnz (ErrMask - CWmask   -2)
.errnz (dummy   - CWmask   -3)


;*******************************************************************************
;
; Emulator stack area
;
;The top of stack pointer CURstk is initialized to the last register 
;in the list; on a real 8087, this corresponds to hardware register 0.
;The stack grows toward lower addresses, so the first push (which is
;hardware register 7) is stored into the second-to-last slot.  This gives
;the following relationship between hardware registers and memory
;locations:
;
; BEGstk --> |    reg 1    |  (lowest memory address)
; 	     |    reg 2    |
; 	     |    reg 3    |
; 	     |    reg 4    |
; 	     |    reg 5    |
; 	     |    reg 6    |
; 	     |    reg 7    |
; 	     |    reg 0    |  <-- Initial top of stack (empty)
; ENDstk -->
;
;This means that the wrap-around case on decrementing CURstk will not
;occur until the last (8th) item is pushed.
;
;Note that the physical register numbers are only used in regard to
;the tag word.  All other operations are relative the current top.


endif