windows-nt/Source/XPSP1/NT/base/ntdll/i386/emerror.asm

472 lines
12 KiB
NASM
Raw Normal View History

2020-09-26 03:20:57 -05:00
page ,132
subttl emerror.asm - Emulator error handler
;***
;emerror.asm - Emulator error handler
;
; Microsoft Confidential
;
; Copyright (c) Microsoft Corporation 1987, 1991
;
; All Rights Reserved
;
;Purpose:
; Emulator error handler
;
;Revision History: (also see emulator.hst)
;
; 10/30/89 WAJ Added this header.
; 11/15/89 WAJ Major changes for Dos32RaiseExcpetion().
; 12/01/89 WAJ Now set cbExceptionInfo correctly.
; 02/08/90 WAJ Fixed GP fault in 32 bit exception handler.
; 09/03/91 JWM Modified entry/exit sequence for DOSX32.
; 02/15/92 JWM Adapted for NT.
;
;*******************************************************************************
ifdef _DOS32EXT
include except32.inc
endif
;*** error_return - return to user code (regardless of error)
;
; This macro returns to user code. It goes to some lengths
; to restore the flags on the instruction immediately before
; the return so that any pending trace trap will be
; acknowledged immediately after the retfd (and before the
; next user instruction) instead of after the instruction
; following the return as would be the case if we returned
; using iretd.
;
; ENTRY ((SS:ESP)) = user's EAX
; ((SS:ESP)+4) = return EIP
; ((SS:ESP)+8) = return CS
; ((SS:ESP)+12) = user's EFLAGS
; EXIT return to user program, above arguments
; popped off stack, user's EAX and EFLAGS
; restored.
error_return macro noerror
ifdef _DOS32EXT
sti ; JWM, 9/3/91
push dword ptr [esp+8] ; JWM, 9/6/91
popfd ; JWM, 9/6/91
endif ; DOS32EXT
ifdef NT386
if DBG
push dword ptr [esp+8] ; On checked build, allow
popfd ; single step to work
endif
endif
iretd
endm
TESTif macro nam
mov bl,err&nam ; default error number
if (nam ge 100h)
test ah,nam/256
else ;not (nam ge 100h)
test al,nam
endif ;(nam ge 100h)
JSNZ signalerror
endm
EM_ENTRY eCommonExceptions
CommonExceptions:
mov ebx,[esp].[OldLongStatus]
and ebx,LongSavedFlags ;preserve condition codes, error flags
or EMSEG:[LongStatusWord],ebx ;merge saved status word, condition codes
pop eax
pop ecx
pop edx
pop ebx
add esp,4 ; toss esp value
pop ebp
pop esi
pop edi
add esp,8 ;toss old PrevCodeOff and StatusWord
pop ds
call Emexcept
error_return noerror
ifdef _DOS32EXT
EmExcept PROC C, OldEIP:DWORD, OldCS:DWORD, OldFlags:DWORD
LOCAL SSAR:DWORD
LOCAL ec:_DX32_CONTEXT
;*
;* Set up SS access rights.
;*
push ds
mov [ec.R_Eax], eax
GetEmData ds,ax
mov eax, ss
lar eax, eax
mov [SSAR], eax
;*
;* Fill in ExceptionContext structure.
;*
mov [ec.NPXContextFlags], NPX_CONTEXT_FULL
mov [ec.R_Edi], edi
mov [ec.R_Esi], esi
mov eax, [ebp]
mov [ec.R_Ebp], eax
lea eax, [OldFlags+4]
mov [ec.R_Esp], eax
mov [ec.R_Ebx], ebx
mov [ec.R_Edx], edx
mov [ec.R_Ecx], ecx
mov eax, EMSEG:[PrevCodeOff]
mov [ec.R_Eip], eax
mov eax, [OldFlags]
mov [ec.EFlags], eax
mov eax, [OldCS]
movzx eax,ax
mov [ec.SegCs], eax
mov ax,ss
movzx eax,ax
mov [ec.SegSs], eax
pop eax
movzx eax,ax
mov [ec.SegDs], eax ; ds was pushed on entry.
mov ax,es
movzx eax,ax
mov [ec.SegEs], eax
mov ax,fs
movzx eax,ax
mov [ec.SegFs], eax
mov ax,gs
movzx eax,ax
mov [ec.SegGs], eax
lea esi, [ec]
add esi, 4
push ebp
call SaveState
pop ebp
lea eax, [ec]
push ds
push es
mov bx, seg FLAT:CURstk
mov ds, ebx
mov es, ebx
push eax
call DOS32RAISEEXCEPTION
add esp, 4
pop es
pop ds
RaiseExceptRet:
or eax, eax
JZ ExceptNotHandled
;*
;* Copy new flags, cs, eip to new stack.
;*
mov ds, [ec.SegSs]
mov esi, [ec.R_Esp] ; ds:esi == new ss:esp
mov eax, [ec.Eflags] ; set up iretd frame
mov [esi-4], eax
mov eax, [ec.SegCs]
mov [esi-8], eax
mov eax, [ec.R_Eip]
mov [esi-12], eax
;*
;* Put new stack pointer on stack.
;*
push ds
sub esi, 12
push esi
;*
;* Reset other registers.
;*
mov edi, [ec.R_Edi]
mov esi, [ec.R_Esi]
mov ebx, [ec.R_Ebx]
mov edx, [ec.R_Edx]
mov ecx, [ec.R_Ecx]
mov eax, [ec.R_Eax]
mov ds, [ec.SegDs]
mov es, [ec.SegEs]
mov fs, [ec.SegFs]
mov gs, [ec.SegGs]
mov ebp, [ec.R_Ebp] ; must do this last.
lss esp, fword ptr [esp] ; reset ss:esp
sti ; JWM, 9/3/91
push [esp+8] ; JWM, 9/6/91
popfd ; JWM, 9/6/91
iretd ; reset flags, cs, eip
ExceptNotHandled:
EmExcept ENDP
endif ; ifdef _DOS32EXT
ifdef NT386
ISIZE equ 4
ISizeEC equ (ContextFrameLength + ISIZE - 1) and (not (ISIZE - 1))
ISizeExceptStruct equ (ExceptionRecordLength + ISIZE - 1) and (not (ISIZE - 1))
ec_off EQU 4+ISizeEc
estruct_off EQU ec_off+ISizeExceptStruct
SSAR EQU <[ebp][-4]>
ec EQU <[ebp][-ec_off]>
eStruct EQU <[ebp][-estruct_off]>
OldEIP EQU <ebp+8>
OldCS EQU <ebp+12>
OldFlags EQU <ebp+16>
EmExcept PROC NEAR
push ebp
mov ebp,esp
sub esp,estruct_off
;*
;* Set up SS access rights.
;*
push ds
mov [ec.ctx_RegEax], eax
GetEmData ds,ax
mov eax, ss
lar eax, eax
mov [SSAR], eax
;*
;* Fill in ExceptionContext structure.
;*
mov dword ptr [ec.ContextFlags], NPX_CONTEXT_FULL
mov dword ptr [ec.ctx_Cr0NpxState], CR0_EM
mov [ec.ctx_RegEdi], edi
mov [ec.ctx_RegEsi], esi
mov eax, [ebp]
mov [ec.ctx_RegEbp], eax
lea eax, [OldFlags+4]
mov [ec.ctx_RegEsp], eax
mov [ec.ctx_RegEbx], ebx
mov [ec.ctx_RegEdx], edx
mov [ec.ctx_RegEcx], ecx
mov eax, [OldEIP]
mov [ec.ctx_RegEip], eax
mov eax, [OldFlags]
mov [ec.ctx_EFlags], eax
mov eax, [OldCS]
movzx eax,ax
mov [ec.ctx_SegCs], eax
mov ax,ss
movzx eax,ax
mov [ec.ctx_SegSs], eax
pop eax
movzx eax,ax
mov [ec.ctx_SegDs], eax ; ds was pushed on entry.
mov ax,es
movzx eax,ax
mov [ec.ctx_SegEs], eax
mov ax,fs
movzx eax,ax
mov [ec.ctx_SegFs], eax
mov ax,gs
movzx eax,ax
mov [ec.ctx_SegGs], eax
lea esi, [ec]
add esi, ctx_env
or EMSEG:[StatusWord], 8000H ; set 'busy' bit
or EMSEG:[SWerr], Summary ; set Summary bit
or EMSEG:[CURerr], Summary
mov cl, EMSEG:[ErrMask]
push ecx
push ebp
call SaveState
pop ebp
pop ecx
call GetEMSEGStatusWord ; EAX = status word
test al, cl ; test status word against mask
jne short Err00
ifdef TRACENPX
mov edx, 0C1020304h ; Raise bogus exception code, to trace with
jmp short Err50
endif
mov al, Invalid
;
; According to the floating error priority, we test what is the cause of
; the NPX error and raise an appropriate exception.
;
Err00:
test al, Invalid ; Invalid Op?
jz short Err10 ; No, go check next
mov edx, XCPT_FLOAT_INVALID_OPERATION
test al, StackFlag ; Stack fault?
jz short Err50 ; No, go raise invalid op
mov edx, XCPT_FLOAT_STACK_CHECK
jmp short Err50 ; Go raise stack fault
Err10: mov edx, XCPT_FLOAT_DIVIDE_BY_ZERO
test al, ZeroDivide
jnz short Err50
mov edx, XCPT_FLOAT_DENORMAL_OPERAND
test al, Denormal
jnz short Err50
mov edx, XCPT_FLOAT_OVERFLOW
test al, Overflow
jnz short Err50
mov edx, XCPT_FLOAT_UNDERFLOW
test al, Underflow
jnz short Err50
mov edx, XCPT_FLOAT_INEXACT_RESULT
Err50: mov [eStruct.ExceptionNum], edx
xor eax,eax
mov [eStruct.fHandlerFlags], eax
mov [eStruct.NestedExceptionReportRecord], eax
mov dword ptr [eStruct.CParameters], 1 ; GeorgioP convention
mov [eStruct.ErExceptionInformation], eax ; GeorgioP convention
mov eax, EMSEG:[PrevCodeOff]
mov [eStruct.ExceptionAddress], eax
lea edx, [eStruct]
lea eax, [ec]
push ds
push es
;TRUE, this is a first-chance exception
stdCall _NtRaiseException,<edx, eax, 1>
stdCall _RtlRaiseStatus, <eax>
pop es
pop ds
RaiseExceptRet:
or eax, eax
JZ ExceptNotHandled
;*
;* Copy new flags, cs, eip to new stack.
;*
mov ds, [ec.ctx_SegSs]
mov esi, [ec.ctx_RegEsp] ; ds:esi == new ss:esp
mov eax, [ec.ctx_Eflags] ; set up iretd frame
mov [esi-4], eax
mov eax, [ec.ctx_SegCs]
mov [esi-8], eax
mov eax, [ec.ctx_RegEip]
mov [esi-12], eax
;*
;* Put new stack pointer on stack.
;*
push ds
sub esi, 12
push esi
;*
;* Reset other registers.
;*
mov edi, [ec.ctx_RegEdi]
mov esi, [ec.ctx_RegEsi]
mov ebx, [ec.ctx_RegEbx]
mov edx, [ec.ctx_RegEdx]
mov ecx, [ec.ctx_RegEcx]
mov eax, [ec.ctx_RegEax]
mov ds, [ec.ctx_SegDs]
mov es, [ec.ctx_SegEs]
mov fs, [ec.ctx_SegFs]
mov gs, [ec.ctx_SegGs]
mov ebp, [ec.ctx_RegEbp] ; must do this last.
lss esp, fword ptr [esp] ; reset ss:esp
sti ; JWM, 9/3/91
push [esp+8] ; JWM, 9/6/91
popfd ; JWM, 9/6/91
iretd ; reset flags, cs, eip
ExceptNotHandled:
EmExcept ENDP
endif ; ifdef NT386
int 3 ; Added For BBT, a return here is needed or BBT
ret ; has a flow problem.
ifdef DEBUG
lab PageFault
mov al, byte ptr cs:[iax]
ret
endif