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