mirror of https://github.com/tongzx/nt5src
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.
336 lines
6.5 KiB
336 lines
6.5 KiB
page ,132
|
|
subttl emfixfly.asm - Fixup-on-the-fly routines
|
|
;***
|
|
;emfixfly.asm - Fixup-on-the-fly routines
|
|
;
|
|
; Copyright (c) 1987-89, Microsoft Corporation
|
|
;
|
|
;Purpose:
|
|
; Fixup-on-the-fly routines
|
|
;
|
|
; This Module contains Proprietary Information of Microsoft
|
|
; Corporation and should be treated as Confidential.
|
|
;
|
|
;Revision History:
|
|
; See emulator.hst
|
|
;
|
|
;*******************************************************************************
|
|
|
|
|
|
;*******************************************************************************
|
|
; 03/29/85 - added 286 optimizations to change FWAITs to NOPs
|
|
; 09/10/87 - added FWAIT's for BASIC error handling
|
|
; 11/02/87 - changed FWFixUpOnFly to check for errors
|
|
;*******************************************************************************
|
|
|
|
|
|
ProfBegin FIXFLY
|
|
|
|
|
|
ifdef DOS3
|
|
|
|
pub SOFixUpOnFly
|
|
sti ; turn on interrupts
|
|
fwait ; For BASIC error handling
|
|
push ax
|
|
push bp
|
|
push ds
|
|
push si
|
|
mov bp,sp ; Point to stack
|
|
lds si,dword ptr 8[bp] ; Fetch ret address,(points to after instruction)
|
|
mov al,[si] ; get ESC byte
|
|
or byte ptr [si],0C0h ; turn back into ESC x byte
|
|
dec si ; Make SI point to start off instruction
|
|
dec si
|
|
mov 8[bp],si ; Change ret address to return to instruction
|
|
shr al,1 ; move 2 bits into correct position
|
|
shr al,1
|
|
shr al,1
|
|
not al ; negate them
|
|
and al,018h ; mask to middle 2 bits
|
|
or al,fES ; turn into correct segmented override
|
|
xchg al,ah ; into high half
|
|
mov al,fFWAIT ; low byte
|
|
mov [si],ax ; stuff it
|
|
push bx
|
|
mov bx,1 ; bx = 1 to skip segment override
|
|
ifdef WF
|
|
jmp fixupdone
|
|
else
|
|
jmp short fixupdone
|
|
endif
|
|
|
|
; new routine - don't back patch - check for error
|
|
; UNDONE - need to change this for Windows - can't edit code
|
|
; need to check errorcode
|
|
|
|
pub FWFixUpOnFly
|
|
sti ; turn on interrupts
|
|
fwait ; For BASIC error handling
|
|
|
|
|
|
ifdef WF
|
|
wfFaultHere = $-1
|
|
; int 3
|
|
push ds ; ds[18] retip[20] retcs[22] retfl[24]
|
|
push es ; es[16]
|
|
pusha ;
|
|
mov bp, sp ;
|
|
mov ax, EMULATOR_DATA
|
|
mov ds, ax
|
|
cmp [wfGoFast], 1
|
|
jnz WinSlow
|
|
push [bp+22] ; faulting CS - get data alias
|
|
push [wfSel]
|
|
call ChangeSelector
|
|
mov es, [wfSel]
|
|
sub word ptr [bp+20], 2
|
|
mov bx, [bp+20] ; point to faulting insn
|
|
xor ax, ax
|
|
xchg [wfInsn], ax
|
|
or ax, ax ; are we here due to fault?
|
|
je wfNoFault
|
|
mov es:[bx], ax ; yes - restore 'fake' INT 3d
|
|
xor ax,ax
|
|
xchg [errorcode],al ; get and reset errorcode
|
|
mov REMLSW, ax ; save error code
|
|
|
|
popa
|
|
pop es
|
|
pop ds
|
|
jmp WinFastContinue
|
|
|
|
; mov ax, 353eh
|
|
; int 21h
|
|
; mov ax, es ; does app have a handler?
|
|
; or ax, bx
|
|
; jz wfDone
|
|
;
|
|
; mov ax, [wfErr]
|
|
;
|
|
; push cs ; return to wfDone
|
|
; push offset wfDone
|
|
;
|
|
; push es ; call app handler
|
|
; push bx
|
|
;
|
|
; retf
|
|
|
|
FWAITNOP equ (iNOP + 256*fFWAIT)
|
|
wfNoFault: ; this was a 'real' INT 3d,
|
|
mov es:[bx], FWAITNOP ; so we'll patch it to inline code
|
|
|
|
wfDone:
|
|
popa
|
|
pop es
|
|
pop ds
|
|
iret
|
|
|
|
WinSlow: ; can't use fast method, fall through
|
|
popa
|
|
pop es
|
|
pop ds ; fall through into old code
|
|
endif
|
|
|
|
ifdef POLLING ; new exception handling under POLLING
|
|
|
|
ifdef USE_IRET
|
|
FWAITiret:
|
|
iret ; Edit to nop if error occurs
|
|
|
|
elseifdef WINDOWS
|
|
|
|
push ds
|
|
push ax
|
|
|
|
mov ax, EMULATOR_DATA
|
|
mov ds, ax
|
|
|
|
cmp [ExceptFlag], 0 ; if not zero, 80x87 exception occured.
|
|
|
|
pop ax
|
|
pop ds
|
|
|
|
jnz PolledException
|
|
|
|
iret
|
|
|
|
else ;DEFUALT
|
|
|
|
FWAITRetF db bRETF ; Edit to 3 byte nop if error occurs
|
|
FWAITRetF2 dw 2
|
|
|
|
endif ;DEFAULT
|
|
|
|
|
|
pub PolledException
|
|
push eax ; same frame as in emerror.asm
|
|
push ds ; get address from task DS
|
|
|
|
ifdef standalone
|
|
xor ax,ax
|
|
mov ds,ax
|
|
mov ds,ds:[4*TSKINT+2]
|
|
|
|
elseifdef _COM_
|
|
mov ds, [__EmDataSeg]
|
|
|
|
else ;not standalone or _COM_
|
|
mov ax,EMULATOR_DATA
|
|
mov ds,ax
|
|
endif ;not standalone or _COM_
|
|
|
|
;*
|
|
;* Reset fwait polling flag.
|
|
;*
|
|
|
|
ifdef USE_IRET
|
|
mov byte ptr cs:[FWAITiret], bIRET ; reset "iret"
|
|
|
|
elseifdef WINDOWS
|
|
mov [ExceptFlag], 0
|
|
|
|
else ;DEFAULT
|
|
mov [FWAITRetF], bRETF ; reset "retf 2"
|
|
mov [FWAITRetF2], 2
|
|
endif ;DEFAULT
|
|
|
|
|
|
xor ax,ax
|
|
xchg [errorcode],al ; get and reset errorcode
|
|
|
|
|
|
ifdef WINDOWS
|
|
mov REMLSW, ax ; save error code
|
|
|
|
pop ds
|
|
pop ax ; stack is now just an int stack frame
|
|
WinFastContinue:
|
|
inc bp
|
|
push bp
|
|
mov bp, sp
|
|
push ds
|
|
|
|
push ax ; save user's ax
|
|
|
|
push cs ; must set up another stack frame
|
|
mov ax, offset FF_DummyReturn
|
|
push ax
|
|
FF_DummyReturn:
|
|
|
|
mov word ptr [bp-2], EMULATOR_DATA ; emulator's ds goes on first frame
|
|
|
|
inc bp
|
|
push bp
|
|
mov bp, sp
|
|
push ds ; push user's ds onto dummy stack frame
|
|
|
|
mov ax, EMULATOR_DATA
|
|
mov ds, ax
|
|
|
|
push es ; if windows => setup SignalAddress for
|
|
push bx ; far call
|
|
|
|
mov ax, DOS_getvector*256 + TSKINT
|
|
IntDOS
|
|
|
|
mov word ptr [SignalAddress], bx
|
|
mov word ptr [SignalAddress+2], es
|
|
|
|
pop bx
|
|
pop es
|
|
|
|
mov ax, REMLSW ; al = error code
|
|
|
|
call [SignalAddress] ; execute signal routine
|
|
|
|
pop ds ; restore user's ds
|
|
add sp, 6 ; get rid of dummy stack frame
|
|
pop ax ; restore user's ax
|
|
|
|
add sp, 2 ; get rid of emulator ds on stack
|
|
|
|
pop bp
|
|
dec bp
|
|
|
|
iret ; return
|
|
|
|
else ;not WINDOWS
|
|
|
|
call [SignalAddress] ; execute signal routine
|
|
|
|
pop ds ; restore user DS
|
|
pop eax
|
|
iret
|
|
|
|
endif ;not WINDOWS
|
|
|
|
|
|
else ;not POLLING
|
|
push ax
|
|
mov ax,FIWRQQ ; isolated FWAIT fixup
|
|
jmp short FixUpOnFly
|
|
endif ;not POLLING
|
|
|
|
pub DSFixUpOnFly
|
|
sti ; turn on interrupts
|
|
fwait ; For BASIC error handling
|
|
push ax
|
|
mov ax,FIDRQQ ; DS segment fixup
|
|
|
|
pub FixUpOnFly
|
|
PUSH BP
|
|
PUSH DS
|
|
PUSH SI
|
|
MOV BP,SP ; Point to stack
|
|
LDS SI,dword ptr 8[BP] ; Fetch ret address,(points to after instruction)
|
|
DEC SI ; Make SI point to instruction
|
|
DEC SI
|
|
MOV 8[BP],SI ; Change ret address to return to instruction
|
|
SUB [SI],ax ; Remove Fixup to convert to 8087 instruction
|
|
push bx
|
|
xor bx,bx ; bx = 0 for no segment override
|
|
|
|
; For the 286 change FWAITs on numeric instructions to NOPs
|
|
;
|
|
; ds:si = FWAIT address
|
|
; ds:(si+bx+1) = 8087/287 instruction
|
|
|
|
pub fixupdone
|
|
push sp ; check for 286
|
|
pop ax
|
|
cmp ax,sp
|
|
jne fixupxit ; not 286
|
|
|
|
mov ax,[bx+si+1] ; get instruction
|
|
and ax,030FBh ; mask for FSTCW/FSTSW/FSTENV/FSAVE
|
|
cmp ax,030D9h ; underlying bits
|
|
jne fixcheck2 ; not one of the above
|
|
mov al,[bx+si+2] ; get 2nd byte of instruction again
|
|
cmp al,0F0h ; check if kernel functions
|
|
jb fixupxit ; no - exit
|
|
|
|
pub fixcheck2
|
|
mov ax,[bx+si+1] ; get instruction
|
|
and ax,0FEFFh ; mask for FCLEX/FINIT
|
|
cmp ax,0E2DBh ; underlying bits
|
|
je fixupxit ; can't remove FWAIT
|
|
|
|
mov ax,[bx+si+1] ; get instruction
|
|
cmp ax,0E0DFh ; check for FSTSW AX
|
|
je fixupxit ; can't remove FWAIT
|
|
|
|
mov byte ptr [si],iNOP ; NOP the FWAIT
|
|
|
|
pub fixupxit
|
|
pop bx
|
|
POP SI
|
|
POP DS
|
|
POP BP
|
|
pop ax
|
|
IRET
|
|
|
|
|
|
endif ;DOS3
|
|
|
|
ProfEnd FIXFLY
|