Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

715 lines
16 KiB

page ,132
title emulator - 8087/287 emulator for MS-DOS, XENIX, OS/2, Windows
;***
;emulator.asm - 8087/287 emulator for MS-DOS, XENIX, OS/2, Windows
;
; Copyright (c) 1984-89, Microsoft Corporation
;
;Purpose:
; 8087/287 emulator for MS-DOS, XENIX, OS/2, Windows
;
; This Module contains Proprietary Information of Microsoft
; Corporation and should be treated as Confidential.
;
;Revision History:
; See emulator.hst
;
;*******************************************************************************
include emulator.hst ; Emulator history file.
major_ver equ 6
minor_ver equ 0
fastSP = 0 ; default to no fast single precision
;*******************************************************************************
;
; Print out emulator version.
;
;*******************************************************************************
OutMsg macro text
ifndef ?QUIET
%out text
endif
endm
outver macro maj,tens,hunds
OutMsg <Emulator Version maj&.&tens&hunds>
endm
if1
outver %major_ver,%(minor_ver/10),%(minor_ver mod 10)
ifdef WINDOWS
OutMsg <Windows 2.00 Emulator>
endif
ifdef QB3
OutMsg <QuickBASIC 3.00 Emulator>
endif
ifdef _NOSTKEXCHLR ; formerly called QB4
OutMsg <No stack overflow/underflow hadler.>
endif
ifdef PCDOS
OutMsg <IBM PC-DOS version - Uses int 11h BIOS equipment check.>
endif
ifdef MTHREAD
ifdef DOS5only
OutMsg <Reentrant multithread OS/2 emulator.>
else
%out *** Error: MTHREAD supported only if DOS5only defined.
endif
endif
ifdef SQL_EMMT
ifdef MTHREAD
OutMsg <Special SQL version.>
else
%out *** Error: SQL supported only if MTHREAD is defined.
endif
endif
ifdef _COM_
OutMsg <COM files supported.>
endif ;_COM_
ifdef XENIX
OutMsg <XENIX emulator.>
PROTECT = 1 ; XENIX is always protect mode
else ;not XENIX
ifdef DOS5only
OutMsg <DOS 5 only emulator.>
DOS5 = 1
PROTECT = 1 ; DOS 5 is always protect mode
else ;not DOS5only
DOS3= 1 ; DOS 3 support is default
ifdef DOS5
OutMsg <DOS 3 & 5 emulator.>
DOS3and5= 1
PROTECT = 1 ; DOS 5 is always protect mode
else ;not DOS5
OutMsg <DOS 3 only emulator.>
endif ;not DOS5
endif ;not DOS5only
ifdef standalone
OutMsg <Stand-alone version (uses task vector for DS).>
ifdef DOS5
%out *** Error: DOS 5 support not allowed.
.error
endif ;DOS5
endif ;standalone
ifdef frontend
OutMsg <Front-end version - No hardware and limited instructions.>
endif ;frontend
ifdef SMALL_EMULATOR
OutMsg <Small Emulator - Limited instructions.>
endif ;SMALL_EMULATOR
ifdef only87
OutMsg <8087 only version - No emulation.>
endif ;only87
ifdef POLLING
OutMsg <Exception handling uses polling FWAITs.>
endif
endif ;not XENIX
ifdef i386
OutMsg <386 version>
endif
if fastSP
%out Fast Single Precision version - Not supported.
endif ;fastSP
ifdef DEBUG
OutMsg <+++ Debug Version +++>
endif ;DEBUG
ifdef PROFILE
OutMsg <Profiling version.>
endif ;PROFILE
endif ;if1
;*******************************************************************************
;
; Include cmacros.inc
;
;*******************************************************************************
?PLM = 1
?WIN = 0
?DF = 1
?NOGLOBAL = 1
?NOSTATIC = 1
?NOEXTERN = 1
?NODEF = 1
?NOPTR = 1
include cmac_mrt.inc ; old, customized masm510 cmacros
include mrt386.inc
ifdef MTHREAD
include os2supp.inc
endif
;*******************************************************************************
;
; Include emulator macros.
;
;*******************************************************************************
include emulator.inc
;*******************************************************************************
;
; Processor setup.
;
;*******************************************************************************
ifdef i386
.386p
.287
elseifdef XENIX
.286c ; allow 286 instructions if XENIX
.287
elseifdef DOS5only
.286c ; allow 286 instructions if DOS 5 only
.287
else ;Default
.8086 ; otherwise only 8086 instructions
.8087 ; make sure there are fwaits before all instruction
endif
;*******************************************************************************
;
; Define segments.
;
;*******************************************************************************
ifdef QB3
createSeg EMULATOR_DATA, edata, para, public, CODE, <>
createSeg EMULATOR_TEXT, ecode, para, public, CODE, <>
elseifdef QP
createSeg DATA, edata, word, public,, <>
createSeg CODE, ecode, word, public,, <>
else ;DEFAULT
createSeg EMULATOR_DATA, edata, para, public, FAR_DATA, <>
createSeg EMULATOR_TEXT, ecode, para, public, CODE, <>
endif ;DEFAULT
;*******************************************************************************
;
; Define Number of stack elements, BEGINT and TSKINT
;
;*******************************************************************************
ifdef XENIX
Numlev equ 10 ; 10 levels minimum for floating point
else ;not XENIX
ifdef QB3
extrn $EM_INT:far ; QB3 emulator error entry
BEGINT equ 084h ; MSDOS beginning interrupt
Numlev equ 10 ; 10 levels minimum for floating point
else ;not QB3
BEGINT equ 034h ; MSDOS beginning interrupt
ifdef _NOSTKEXCHLR
Numlev equ 10 ; 10 levels minimum for floating point
elseifdef MTHREAD
Numlev equ 16 ; 16 levels minimum for floating-point
else ;Default
Numlev equ 16 ; 16 levels minimum for floating point
endif ;Default
ifdef standalone
TSKINT equ BEGINT + 10 ; Task data pointer
endif
ifdef WINDOWS
TSKINT equ BEGINT + 10 ; SignalAddress pointer
endif
endif ;not QB3
ifdef WINDOWS
FIDRQQ equ (fINT + 256*(BEGINT + 0)) - (fFWAIT + 256*fESCAPE)
FIERQQ equ (fINT + 256*(BEGINT + 8)) - (fFWAIT + 256*fES)
FIWRQQ equ (fINT + 256*(BEGINT + 9)) - (iNOP + 256*fFWAIT)
FIARQQ equ (fINT + 256*(BEGINT + 8)) - (fFWAIT + 256*fDS)
FJARQQ equ 256*(((0 shl 6) or (fESCAPE and 03Fh)) - fESCAPE)
FISRQQ equ (fINT + 256*(BEGINT + 8)) - (fFWAIT + 256*fSS)
FJSRQQ equ 256*(((1 shl 6) or (fESCAPE and 03Fh)) - fESCAPE)
FICRQQ equ (fINT + 256*(BEGINT + 8)) - (fFWAIT + 256*fCS)
FJCRQQ equ 256*(((2 shl 6) or (fESCAPE and 03Fh)) - fESCAPE)
elseifdef QP ; QuickPascal can't do absolutes
FIDRQQ equ (fINT + 256*(BEGINT + 0)) - (fFWAIT + 256*fESCAPE)
FIERQQ equ (fINT + 256*(BEGINT + 8)) - (fFWAIT + 256*fES)
FIWRQQ equ (fINT + 256*(BEGINT + 9)) - (iNOP + 256*fFWAIT)
FIARQQ equ (fINT + 256*(BEGINT + 8)) - (fFWAIT + 256*fDS)
FJARQQ equ 256*(((0 shl 6) or (fESCAPE and 03Fh)) - fESCAPE)
FISRQQ equ (fINT + 256*(BEGINT + 8)) - (fFWAIT + 256*fSS)
FJSRQQ equ 256*(((1 shl 6) or (fESCAPE and 03Fh)) - fESCAPE)
FICRQQ equ (fINT + 256*(BEGINT + 8)) - (fFWAIT + 256*fCS)
FJCRQQ equ 256*(((2 shl 6) or (fESCAPE and 03Fh)) - fESCAPE)
else ;not WINDOWS or QuickPascal
extrn FIWRQQ:abs, FIERQQ:abs, FIDRQQ:abs
extrn FISRQQ:abs, FJSRQQ:abs
extrn FIARQQ:abs, FJARQQ:abs
extrn FICRQQ:abs, FJCRQQ:abs
endif ;not WINDOWS or QuickPascal
endif ;not XENIX
;*******************************************************************************
;
; List external functions.
;
;*******************************************************************************
ifdef WINDOWSP
extrn DOS3CALL:far
endif
ifdef WINDOWS
extrn __WINFLAGS:abs
extrn ALLOCDSTOCSALIAS:far
extrn FREESELECTOR:far
ifdef WF
extrn ALLOCSELECTOR:far
;if we are linking to LIBW from Win 3.0, CS isn't found, use PCS
CHANGESELECTOR equ <PRESTOCHANGOSELECTOR>
extrn CHANGESELECTOR:far
endif
endif
ifdef DOS3and5
os2extrn DOSGETMACHINEMODE
endif ;DOS3and5
ifdef DOS5
ifndef frontend
ifndef only87
os2extrn DOSWRITE ; only needed to print out "NO87="
endif ;only87
os2extrn DOSCREATECSALIAS
os2extrn DOSFREESEG
os2extrn DOSDEVCONFIG
endif ;not frontend
os2extrn DOSSETVEC
ifdef MTHREAD
os2extrn DOSALLOCSEG
os2extrn DOSEXIT
extrn __FarGetTidTab:far
endif ;MTHREAD
endif ;DOS5
;*******************************************************************************
;
; Include some more macros and constants.
;
;*******************************************************************************
include emdoc.asm
include emintern.asm
ifdef MTHREAD
include emthread.asm
endif ;MTHREAD
subttl emulator.asm - Emulator Task DATA Segment
page
;*********************************************************************;
; ;
; Emulator Task DATA Segment ;
; ;
;*********************************************************************;
sBegin edata
; eventually this needs to be a big struct
glb <REMLSW,InitControlWord,CURerr>
glb <UserControlWord,UserStatusWord,Have8087>
glb <ControlWord,CWcntl,StatusWord,SWcc>
glb <BASstk,CURstk,LIMstk>
;*******************************************************************************
;
; Order of information here must not change (for CodeView debugging).
; Check with CodeView guys before changing.
;
;*******************************************************************************
ifndef i386
glb <SignalAddress>
nedd SignalAddress,<1 dup (?)> ; Error signal address
endif
Have8087 db 0 ; Is a real 8087 present (0 = no 8087)
Einstall db 0 ; Emulator installed flag (XENIX sets to 1)
UserControlWord dw ? ; User level control word
UserStatusWord dw ? ; User level exception status word
ControlWord label word
CWmask db ? ; exception masks
CWcntl db ? ; arithmetic control flags
StatusWord label word
SWerr db ? ; Initially no exceptions (sticky flags)
SWcc db ? ; Condition codes from various operations
ifdef XENIX
nedw BASstk,<?> ; init to BEGstk + 8*Have8087*Reg87Len
; = start of memory (+ 8 regs if 8087)
nedw CURstk,<?> ; init to BASstk = start of stack
nedw LIMstk,<?> ; ENDstk - 1 reg = end of memory
else ;not XENIX
nedw BASstk,<offset BEGstk> ; init to BEGstk + 8*Have8087*Reg87Len
; = start of memory (+ 8 regs if 8087)
nedw CURstk,<?> ; init to BASstk = start of stack
nedw LIMstk,<offset ENDstk-(2*Reg87Len)> ; ENDstk - 1 reg = end of memory
endif ;not XENIX
;*******************************************************************************
;
; End of fixed area
;
;*******************************************************************************
ifdef DOS3and5
glb <protmode>
protmode dw ? ; Protect mode flag (0 = real)
endif ;DOS3and5
ifdef POLLING ; used by new POLLING exception code
ifdef DOS3
glb <errorcode>
errorcode db 0 ; error code
db 0
endif ;DOS3
endif ;POLLING
ifdef QB3
initCW dw ? ; QB3 initial control word
endif
InitControlWord equ 1332H ; Default - Affine, Round near,
; 64 bits, all exceptions unmasked
NewStatusWord label word ; space for status after reexecution
CURerr dw ? ; initially 8087 exception flags clear
; this is the internal flag reset after
; each operation to detect per instruction
; errors
ifndef XENIX
glb <env_seg>
env_seg dw ? ; environment segment
endif
REMLSW dw ? ; sometimes used as a temp
dw ? ; (2 or 4 bytes)
ifndef XENIX
ifdef DOS5only
NUMVEC= 2 ; coprocesser no present + exception
else
NUMVEC= 11 ; 8 DS + 1 segovr + 1 fwait + 1 task
endif ;DOS5only
glb <oldvec>
oldvec dd NUMVEC dup (0) ; old interrupt vector values
endif
;Transcendental working variables
glb <Reg8087ST0,TEMP1>
Reg8087ST0 label word
TEMP1 dw Reg87Len/2 DUP (?)
ifndef frontend
ifdef DOS5
SSalias dw ? ; SSalias for exception handler
endif ;DOS5
endif ;frontend
ifdef DOS3
ifndef frontend
glb <statwd>
statwd dw 0 ; Location for 8087 status/control word
endif ;frontend
endif ;DOS3
ifndef only87
glb <TEMP2,TEMP3,ARG2,DENORX,COEFFICIENT,RESULT,DAC>
TEMP2 dw Reg87Len/2 DUP (?)
TEMP3 dw Reg87Len/2 DUP (?)
ARG2 dw Reg87Len/2 DUP (?)
DENORX dw Reg87Len/2 DUP (?)
COEFFICIENT dw Reg87Len/2 DUP (?)
nedw RESULT,<?>
DAC dw MantissaByteCnt/2 DUP (?)
endif ;only87
ifndef frontend
ifndef SMALL_EMULATOR
loopct dw 0 ; data for FPREM emulation
bigquot dw 0 ; quotient > 65535 ?
endif ;not SMALL_EMULATOR
endif ;not frontend
ExtendStack dw 1 ; 1 => extend 80x87 stack
ifdef WINDOWS
Installed dw 0 ; Installation flag
ExceptFlag db 0 ; 80x87 exception flag for polling.
db 0
ifdef WF
wfInsn dw 0 ; instruction we overwrote with INT 3d
wfSel dw 0 ; selector to use for alias
wfErr dw 0 ; FP error code (YAEC)
wfGoFast dw 0 ; 1 if we are Enhanced with coproc
endif
public OldNMIVec
OldNMIVec dd 0 ; Old value in 8087 exception interrupt vector
endif ;WINDOWS
ifdef LOOK_AHEAD
NextOpCode db 0 ; first byte of next instruction
LookAheadRoutine dw 0
endif
; Emulator stack area
glb <BEGstk,ENDstk>
BEGstk db Numlev*Reg87Len dup (?) ; emulator stack area
ENDstk label byte
ifdef MTHREAD
cvtbufsize= 349 ; see \clib\include\cvt.h
cvtbuf db cvtbufsize dup (?) ; used by ecvt/fcvt
; routines
endif ;MTHREAD
public __fptaskdata
__fptaskdata label byte ; task data pointer and size
; (if linked with user program)
sEnd edata
subttl emulator.asm
page
;*********************************************************************;
; ;
; Start of Code Segment ;
; ;
;*********************************************************************;
sBegin ecode
assumes cs, ecode
assumes ds, edata
public __fpemulatorbegin
__fpemulatorbegin: ; emulator really starts here
reservedspace: ; IMPORTANT: Must be EMULATOR_TEXT:0000
EMver ; IMPORTANT: Emulator version number
; IMPORTANT: EBASIC needs this here!
db 'gfw...GW'
ifdef _COM_
extrn __EmDataSeg:word
endif ;_COM_
page
ifdef XENIX
include emxenix.asm ; XENIX initialization
elseifdef WINDOWS
include emwin.asm ; WINDOWS initialization
else ;not XENIX or WINDOWS
include emdos.asm ; DOS initialization
endif ;not XENIX or WINDOWS
include emstack.asm ; stack management macros
ifndef QB3 ; no exception handling for QB3
ifndef XENIX ; UNDONE - no exception handling for XENIX
ifndef frontend
include emexcept.asm ; oem independent 8087 exception handling
endif ;frontend
endif ;XENIX ; UNDONE - at this time
endif ;QB3
include emerror.asm ; error handler
ifndef XENIX ; not used with XENIX
include emspec.asm ; special emulator/8087 functions
ifndef frontend
include emfixfly.asm ; fixup on the fly
endif ;not frontend
endif ;not XENIX
ifndef only87
public __fpemulator
__fpemulator: ; emulator starts here
include emdisp.asm ; dispatch tables
include emconst.asm ; constants
ifdef i386
include em386.asm ; 386 emulation/initialization entry
else
include emmain.asm ; main entry and address calculation
endif
include emdecode.asm ; instruction decoder
include emarith.asm ; arithmetic dispatcher
include emfadd.asm ; add and subtract
include emfmul.asm ; multiply
include emfdiv.asm ; division
include emnormal.asm ; normalize and round
include emlssng.asm ; load and store single
include emlsdbl.asm ; load and store double
include emlsint.asm ; load and store integer
include emlsquad.asm ; load and store quadword integer
include emfrndi.asm ; round to integer
include emlstmp.asm ; load and store temp real
include emfmisc.asm ; miscellaneous instructions
include emfcom.asm ; compare
include emfconst.asm ; constant loading
include emnew.asm ; new instructions: f<op> ST(i)
ifndef frontend
ifndef SMALL_EMULATOR
include emfprem.asm ; partial remainder
include emfsqrt.asm ; square root
include emftran.asm ; transcendentals
endif ;not SMALL_EMULATOR
endif ;not frontend
endif ;not only87
public __fpemulatorend
__fpemulatorend: ; emulator ends here
sEnd ecode
ifdef WINDOWS
EM_END equ <end LoadTimeInit>
else
EM_END equ <end>
endif
EM_END