446 lines
12 KiB
PHP
446 lines
12 KiB
PHP
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
|