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 , 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, elseif dist eq 3 db 3DH,0 ;cmp eax, elseif dist eq 2 db 66H,3DH ;cmp ax, elseif dist eq 1 db 3CH ;cmp al, else .err endif ifnb .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