|
|
page ,132 subttl emwin.asm - Initialization and Termination for Windows ;*** ;emwin.asm - Initialization and Termination for Windows ; ; Copyright (c) 1987-89, Microsoft Corporation ; ;Purpose: ; Initialization and Termination for Windows ; ; This Module contains Proprietary Information of Microsoft ; Corporation and should be treated as Confidential. ; ;Revision History: ; See emulator.hst ; ;*******************************************************************************
comment !
Windows/DOS interfaces to emulator/8087 functions
Certain emulator/8087 functions are performed by calling __fpmath with an function code and arguments.
__fpmath general floating point math package interface used by the emulator/8087 and float calls interfaces. This is a far routine and must be far called.
entry:
bx = 0 initialize floating point math (program startup) dx, ax, si input values ignored in WINDOWS emulator returns: ax = 0 if successful and using software floating point 1 if successful and using 8087 just terminates process if error
bx = 1 reset (FINIT) - finit ok even under WINDOWS; typical usage will load control word afterward so other tasks won't be hindered (as with _fpreset() call)
bx = 2 terminate floating point math (program termination)
bx = 3 set error signal address dx:ax = segment:offset of user error handler
bx = 4 load user control word (user should not use FLDCW instruction directly) ax = user control word value
bx = 5 store user control word returns: ax = user control word value
bx = 6 truncate TOS to integer TOS ax = user control word (only use round mode)
bx = 7 truncate TOS to 32-bit integer in DX:AX ax = user control word (only use round mode)
bx = 8 store user status word returns: ax = user status word value
bx = 9 clear exceptions
bx = 10 return number of stack elements in ax
bx = 11 returns 1 if using 80x87, 0 if not
bx = 12 if ax = 0, turn off extended stack. if ax = 1, turn on e.s.
!
glb <functab>
functab label word
dw initialization ; 0 - initialize emulator/8087 dw reset ; 1 - reset emulator/8087 stack dw termination ; 2 - terminate emulator/8087 dw setsignal ; 3 - set error signal address dw loadcontrolword ; 4 - load user control word dw storecontrolword ; 5 - store user control word dw truncateTOS ; 6 - truncate TOS to integer TOS dw truncateTOSto32int ; 7 - truncate TOS to integer in DX:AX dw storestatusword ; 8 - store user status word dw clearexceptions ; 9 - clear execeptions dw NumStack ; 10 - report number of elements in stack dw ReturnHave8087 ; 11 - report if using coprocessor dw SetExtendedStack ; 12 - turn on or off extended stack endfunc label word
SizeJmpTab equ 12
sEnd ecode
sBegin ecode
assumes cs, ecode assumes ds, edata
public __fpmath
__fpmath proc far
cmp bx, SizeJmpTab ja RetFPErr
shl bx, 1 push ds ; save DS
mov cx, EMULATOR_DATA mov ds, cx
call functab[bx]
pop ds ; restore DS
EmuRet: ret
RetFPErr: or ax, -1 cwd jmp EmuRet
__fpmath endp
subttl emwin.asm - Initialization and Termination page ;*********************************************************************; ; ; ; Initialization and Termination ; ; ; ;*********************************************************************;
wastetime macro push cx mov cx,20 ;; wait for a short time loop $ pop cx endm
; program initialization ; ; entry dx:ax = task data area (segment and size) for standalone ; si = DOS environment segment for NO87 lookup ??? ; DX,AX,SI - ignored in WINDOWS case ; these register inputs are ignored for Windows app ; program-time initialization
pub initialization ; all initialization is done when loaded
ifdef WF cmp [Installed],0 jnz @F .286p push 0 call AllocSelector mov [wfSel], ax ; Error checking?? mov ax, __WINFLAGS ; int 3 test ax, WF_WIN386 jz wfSlow1 cmp [Have8087], 0 je wfSlow1 or [wfGoFast], 1 ; We can use fast if Enh Mode & FPU wfSlow1: @@: endif inc [Installed] ; Installed will count number of apps ; using the emulator.
cmp [Have8087], 0 ; check for 8087/80287 je NoInstall87
extrn __FPINSTALL87:near call __FPINSTALL87 ; set NMI (int 2) for this instance NoInstall87:
call reset xor ax, ax
ret
ifdef standalone mov di,offset BEGstk ; di = base of register stack mov [BASstk],di ; initialize stack base mov cx,Reg87Len ; cx = register length xchg ax,dx ; ax = task data segment size sub ax,di ; ax = number bytes for stack cwd ; dx:ax = number of bytes div cx ; ax = number of entries mul cx ; ax = number of bytes add ax,di ; ax = top of stack sub ax,cx ; Leave room for one on overflow mov [LIMstk],ax ; set top of stack endif ;standalone
; check if floating point emulator/8087 already installed (device driver)
; load time initialization
pub LoadTimeInit
push di push si push ds mov ax,EMULATOR_DATA mov ds,ax
mov ax, __WINFLAGS and ax, WF_80x87 cmp ax, WF_80x87 jz WinHave87
ifdef only87 jmp loadiniterrorret endif jmp WinSet87
pub WinHave87 mov al,1
pub WinSet87 mov [Have8087],al
; real mode emulation and fixup on the fly vector setup
pub initvec call SaveVectors call SetVectors
pub loadinitfinish
; finish initialization
pub initfinish
mov [Installed], 0 ; Installed will count number of apps
call reset ; reset (0), FINIT if 8087 present and ; set up default control word
mov ax, 1 ; return non zero result
pub loadiniterrorret
pop ds pop si pop di retf ; far return for dynalink lib entry pt.
;* ;* DLL termination routine. ;*
public WEP WEP label far
push ds push ax
push si push di
mov ax,EMULATOR_DATA mov ds,ax
call reset call RestoreVectors
pop di pop si pop ax pop ds
retf 2 ; WEP functions are called with a word paramater.
;------ program termination ----------------------------------------------------
pub termination
call reset ; reset chip for other apps
dec [Installed] ; if Installed is not 0, someone is jnz termrealdone ; still using the emulator.
ifdef WF xor ax, ax xchg ax, [wfSel] or ax, ax jz @F push ax call FreeSelector @@: endif
ifndef only87 cmp [Have8087],0 ; Non zero if 8087 chip exists je termrealdone endif ;only87
extrn __FPTERMINATE87:near ; reset NMI (int 2) for this instance call __FPTERMINATE87
pub termrealdone ret
subttl emwin.asm - reset and clearexceptions page ;*********************************************************************; ; ; ; Reset and Clearexceptions ; ; ; ;*********************************************************************;
pub reset
ifndef only87 cmp [Have8087],0 ; Nonzero if 8087 chip exists je NoFINIT endif ;only87 fninit fwait ; Workaround for 80387 bug. fninit
pub NoFINIT mov ax, [BASstk] mov [CURstk], ax ; reset stack to bottom
mov ax, InitControlWord ; setup initial control word call loadcontrolword
; fall into clearexceptions
pub clearexceptions
xor ax, ax ifndef only87 cmp al, [Have8087] ; Nonzero if 8087 chip exists je NoFCLEX endif ;only87 fclex ; clear exceptions
pub NoFCLEX ifndef only87 mov [StatusWord], ax ; clear status word endif ;only87 mov [UserStatusWord], ax ; clear exception status word
ret
subttl emwin.asm - setsignal --------------------------------- page ;*********************************************************************; ; ; ; Setsignal ; ; ; ;*********************************************************************;
pub setsignal
push ds
mov ds, dx ; set TSKINT to SignalAddress mov dx, ax mov ax, 25h*256 + TSKINT IntDOS
pop ds ret
pub SaveVectors
mov cx, NUMVEC ; save old vectors under DOS 3 mov ax, 35h*256 + BEGINT ; get vector mov di, offset oldvec ; di = old vector table
pub getvecs IntDOS inc ax mov [di], bx ; save old vector mov [di+2], es add di, 4 loop getvecs
ret
pub SetVectors
ifndef only87 mov dx, offset DStrap ; assume emulator mov si, offset SOtrap mov di, offset FWtrap ifdef WINDOWS mov ax, __WINFLAGS ; if we are in PMODE & win386 increment all of and ax, WF_PMODE or WF_WIN386 ; the handler address past the "sti". cmp ax, WF_PMODE or WF_WIN386 jne NotPmode1
inc dx inc si inc di lab NotPmode1 endif ;WINDOWS
cmp [Have8087], 0 ; are we using 8087 ? jz SetEmVecs ; no - go ahead and set them endif ;only87
mov dx, offset DSFixUpOnFly ; set up for fixup-on-the-fly mov si, offset SOFixUpOnFly mov di, offset FWFixUpOnFly ifdef WINDOWS mov ax, __WINFLAGS ; if we are in PMODE & win386 increment all of and ax, WF_PMODE or WF_WIN386 ; the handler address past the "sti". cmp ax, WF_PMODE or WF_WIN386 jne NotPmode2
inc dx inc si inc di lab NotPmode2 endif ;WINDOWS
pub SetEmVecs push ds
push cs pop ds mov ax, 25h*256 + BEGINT mov cx, 8 ; 8 vectors for DStrap
pub SetDSLoop IntDOS ; set vector inc ax ; bump to next one loop SetDSLoop
mov dx, si ; set Segtrap IntDOS inc ax mov dx, di ; set FWtrap IntDOS
pop ds ; restore task data area
ret
pub RestoreVectors
mov cx, NUMVEC mov ax, 25h*256 + BEGINT ; Dos set vector. mov di, offset oldvec ; di = old vector table
pub ResetVecLoop push ds lds dx, [di] ; get old vector value IntDOS pop ds inc ax add di,4
loop ResetVecLoop
ret
pub NumStack ; returns the number of stack elements in ax
xor dx, dx ; dx will count nonzero elements
ifndef only87 cmp Have8087, 0 je CountEmulatorStack endif ;only87
sub sp, 14 ; need 14 bytes for fstenv mov bx, sp fstenv ss:[bx] fldcw ss:[bx] ; reset control word mov ax, ss:[bx+4] ; put tag word in ax add sp, 14 ; reset stack
mov cx, 8 pub NotEmptyLoop mov bx, ax
shr ax, 1 shr ax, 1
and bx, 3 cmp bx, 3 je StackEntryEmpty
inc dx ; stack element was not empty pub StackEntryEmpty loop NotEmptyLoop
pub CountEmulatorStack
mov ax, CURstk sub ax, BASstk
mov bl, Reg87Len
div bl
add ax, dx ; add elements on 80x87 stack
ret
ReturnHave8087 proc near
mov al, [Have8087] cbw
ret ReturnHave8087 endp
SetExtendedStack proc near
mov [ExtendStack], ax
ret SetExtendedStack endp
;*** ;int far pascal __Win87EmInfo( WinInfoStruct far * p, int cb ); ; ;Purpose: ; returns information about win87em.exe to CodeView ; ;Entry: ; WinInfoStruct far * p ; int cb - size of WinInfoStruct ; ;Exit: ; returns non zero if error. ; ; ;Uses: ; ;Exceptions: ; ;*******************************************************************************
cProc __WIN87EMINFO,<PUBLIC,FAR,PLM>,<ds>
parmD p parmW cb
cBegin or ax, -1 cmp [cb], size WinInfoStruct jb WIDone
mov ax, edataBASE mov es, ax assumes es, edata
lds bx, [p] assumes ds, nothing
mov [bx.WI_Version], (major_ver shl 8) + minor_ver mov [bx.WI_SizeSaveArea], Size80x87Area + edataOFFSET __fptaskdata mov [bx.WI_WinDataSeg], es mov [bx.WI_WinCodeSeg], cs
mov al, [Have8087] cbw mov [bx.WI_Have80x87], ax assumes es, nothing
xor ax, ax ; return 0 if no error mov [bx.WI_Unused], ax WIDone: cEnd
;*** ;int far pascal __Win87EmSave( void far * p, int cb ); ; ;Purpose: ; saves win87em.exe info in p ; ;Entry: ; void far * p - pointer to save area. ; int cb - size of save area. ; ;Exit: ; returns non zero if error. ; ;Uses: ; ;Exceptions: ; ;*******************************************************************************
cProc __WIN87EMSAVE,<PUBLIC,FAR,PLM>,<ds,si,di>
parmD p parmW cb
cBegin or ax, -1 cmp [cb], Size80x87Area + edataOFFSET __fptaskdata jb WSDone
mov ax, edataBASE mov ds, ax assumes ds, edata
les di, [p] assumes es, nothing
cmp [Have8087], 0 je NoSave80x87
fsave es:[di.WSA_Save80x87] NoSave80x87:
add di, (WSA_SaveEm - WSA_Save80x87) xor si, si mov cx, edataOFFSET __fptaskdata shr cx, 1
rep movsw
jnc NoSaveLastByte movsb NoSaveLastByte:
xor ax, ax ; return 0 if no error.
WSDone: cEnd
;*** ;int far pascal __Win87EmRestore( void far * p, int cb ); ; ;Purpose: ; retores win87em.exe info from p ; ;Entry: ; void far * p - pointer to save area. ; int cb - size of save area. ; ;Exit: ; returns non zero if error. ; ;Uses: ; ;Exceptions: ; ;*******************************************************************************
cProc __WIN87EMRESTORE,<PUBLIC,FAR,PLM>,<ds,si,di>
parmD p parmW cb
cBegin or ax, -1 cmp [cb], Size80x87Area + edataOFFSET __fptaskdata jb WRDone
mov ax, edataBASE mov es, ax assumes es, edata
lds si, [p] assumes ds, nothing
add si, (WSA_SaveEm - WSA_Save80x87) xor di, di mov cx, edataOFFSET __fptaskdata shr cx, 1
rep movsw
jnc NoRestoreLastByte movsb NoRestoreLastByte:
mov si, [OFF_p] ; reset source pointer.
cmp [Have8087], 0 je NoRestore80x87
frstor [si.WSA_Save80x87] NoRestore80x87:
xor ax, ax ; return 0 if no error.
WRDone: cEnd
assumes ds, edata assumes es, nothing
|