summaryrefslogtreecommitdiffstats
path: root/private/crt32/misc/i386/exsup3.asm
diff options
context:
space:
mode:
Diffstat (limited to 'private/crt32/misc/i386/exsup3.asm')
-rw-r--r--private/crt32/misc/i386/exsup3.asm290
1 files changed, 290 insertions, 0 deletions
diff --git a/private/crt32/misc/i386/exsup3.asm b/private/crt32/misc/i386/exsup3.asm
new file mode 100644
index 000000000..ff8a91dfa
--- /dev/null
+++ b/private/crt32/misc/i386/exsup3.asm
@@ -0,0 +1,290 @@
+;***
+;exsup3.asm
+;
+; Copyright (c) 1994 Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; Exception handling for i386. This is just the C9.0 version of
+; the language-specific exception handler. The C8.0 version is
+; found in exsup2.asm, and the routines common to both C8 and C9
+; are found in exsup.asm.
+;
+;Notes:
+;
+;Revision History:
+; 01-10-94 PML Create VC/C++ 2.0 (C9.0) version from C8.0 original
+;
+;*******************************************************************************
+
+;hnt = -D_WIN32_ -Dsmall32 -Dflat32 -Mx $this;
+
+;Define small32 and flat32 since these are not defined in the NT build process
+small32 equ 1
+flat32 equ 1
+
+ifdef _WIN32_
+_WIN32_OR_POSIX_ equ 1
+endif
+ifdef _POSIX_
+_WIN32_OR_POSIX_ equ 1
+endif
+
+.xlist
+include pversion.inc
+?DFDATA = 1
+?NODATA = 1
+include cmacros.mas
+include exsup.inc
+.list
+
+;REVIEW: can we get rid of _global_unwind2, and just use
+; the C runtimes version, _global_unwind?
+
+extrn __global_unwind2:near
+extrn __local_unwind2:near
+
+;typedef struct _EXCEPTION_REGISTRATION PEXCEPTION_REGISTRATION;
+;struct _EXCEPTION_REGISTRATION{
+;/* _esp, xpointers at negative offset */
+; int _esp;
+; PEXCEPTION_POINTERS xpointers;
+; struct _EXCEPTION_REGISTRATION *prev;
+; void (*handler)(PEXCEPTION_RECORD, PEXCEPTION_REGISTRATION, PCONTEXT, PEXCEPTION_RECORD);
+; struct scopetable_entry *scopetable;
+; int trylevel;
+;};
+;private (at negative offsets from node ptr)
+ _esp = -8
+ xpointers = -4
+_C9_EXCEPTION_REGISTRATION struc ; C9.0 version
+;public:
+ dd ? ; prev (common)
+ dd ? ; handler (common)
+;private:
+ scopetable dd ?
+ trylevel dd ?
+_C9_EXCEPTION_REGISTRATION ends
+FRAME_EBP_OFFSET equ 16
+
+;#define EXCEPTION_MAXIMUM_PARAMETERS 4
+;typedef struct _EXCEPTION_RECORD EXCEPTION_RECORD;
+;typedef EXCEPTION_RECORD *PEXCEPTION_RECORD;
+;struct _EXCEPTION_RECORD{
+; NTSTATUS ExceptionCode;
+; ULONG ExceptionFlags;
+; struct _EXCEPTION_RECORD *ExceptionRecord;
+; PVOID ExceptionAddress;
+; ULONG NumberParameters;
+; ULONG ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
+;};
+_EXCEPTION_RECORD struc
+ exception_number dd ?
+ exception_flags dd ?
+ exception_record dd ?
+ exception_address dd ?
+ number_parameters dd ?
+ exception_information dd 4 dup(?)
+_EXCEPTION_RECORD ends
+SIZEOF_EXCEPTION_RECORD equ 36
+
+;/* following is the structure returned by the _exception_info() intrinsic. */
+;typedef struct _EXCEPTION_POINTERS EXCEPTION_POINTERS;
+;typedef struct EXCEPTION_POINTERS *PEXCEPTION_POINTERS;
+;struct _EXCEPTION_POINTERS{
+; PEXCEPTION_RECORD ExceptionRecord;
+; PCONTEXT Context;
+;};
+_EXCEPTION_POINTERS struc
+ ep_xrecord dd ?
+ ep_context dd ?
+_EXCEPTION_POINTERS ends
+SIZEOF_EXCEPTION_POINTERS equ 8
+
+assumes DS,DATA
+assumes FS,DATA
+
+__except_list equ 0
+
+;struct _SCOPETABLE_ENTRY{
+; int enclosing_level; /* lexical level of enclosing scope */
+; int (*filter)(PEXCEPTION_RECORD); /* NULL for a termination handler */
+; void (*specific_handler)(void); /* xcpt or termination handler */
+;};
+;struct _SCOPETABLE_ENTRY Scopetable[NUMTRYS];
+_SCOPETABLE_ENTRY struc
+ enclosing_level dd ?
+ filter dd ?
+ specific_handler dd ?
+_SCOPETABLE_ENTRY ends
+
+BeginCODE
+if @Version LT 600
+ifdef _WIN32_OR_POSIX_
+;this needs to go here to work around a masm5 bug. (emits wrong fixup)
+assumes CS,FLAT
+else
+assumes CS,CODE
+endif
+endif
+
+;/* _EXCEPT_HANDLER3 - Try to find an exception handler listed in the scope
+; * table associated with the given registration record, that wants to accept
+; * the current exception. If we find one, run it (and never return).
+; * RETURNS: (*if* it returns)
+; * DISPOSITION_DISMISS - dismiss the exception.
+; * DISPOSITION_CONTINUE_SEARCH - pass the exception up to enclosing handlers
+; */
+;int _except_handler3(
+; PEXCEPTION_RECORD exception_record,
+; PEXCEPTION_REGISTRATION registration,
+; PCONTEXT context,
+; PEXCEPTION_REGISTRATION dispatcher)
+;{
+; int ix, filter_result;
+;
+; for(ix=registration->trylevel; ix!=-1; ix=registration->xscope[ix].enclosing_level){
+; /* if filter==NULL, then this is an entry for a termination handler */
+; if(registration->xscope[ix].filter){
+; /* NB: call to the filter may trash the callee save
+; registers. (this is *not* a standard cdecl function) */
+; filter_result=(*registration->xscope[ix].filter)(xinfo);
+; if(filter_result==FILTER_DISMISS)
+; return(-1); /* dismiss */
+; if(filter_result==FILTER_ACCEPT){
+; _global_unwind2(registration);
+; _local_unwind2(registration, ix);
+; (*registration->xscope[ix].specific_handler)(void);
+; assert(UNREACHED); /*should never return from handler*/
+; }
+; assert(filter_result==FILTER_CONTINUE_SEARCH);
+; }
+; }
+; return(0); /* didnt find one */
+;}
+ db 'VC20' ;; VC/C++ 2.0/32-bit (C9.0) version
+ db 'XC00' ;; so debugger can recognize this proc (cuda:3936)
+cProc _except_handler3,<C,PUBLIC>,<IBX,ISI,IDI,IBP>
+ parmDP xrecord
+ parmDP registration
+ parmDP context
+ parmDP dispatcher
+ localV xp,SIZEOF_EXCEPTION_POINTERS
+cBegin
+ ;4*4b for callee saves + 4b return address + 4b param = 24
+
+ ;DF in indeterminate state at time of exception, so clear it
+ cld
+
+ mov ebx, registration ;ebx= PEXCEPTION_REGISTRATION
+ mov eax, xrecord
+
+ test [eax.exception_flags], EXCEPTION_UNWIND_CONTEXT
+ jnz short _lh_unwinding
+
+ ;build the EXCEPTION_POINTERS locally store its address in the
+ ; registration record. this is the pointer that is returned by
+ ; the _eception_info intrinsic.
+ mov xp.ep_xrecord, eax
+ mov eax, context
+ mov xp.ep_context, eax
+ lea eax, xp
+ mov [ebx.xpointers], eax
+
+ mov esi, [ebx.trylevel] ;esi= try level
+ mov edi, [ebx.scopetable] ;edi= scope table base
+_lh_top:
+ cmp esi, -1
+ je short _lh_bagit
+ lea ecx, [esi+esi*2] ;ecx= trylevel*3
+ cmp dword ptr [(edi+ecx*4).filter], 0
+ je short _lh_continue ;term handler, so keep looking
+
+ ;filter may trash *all* registers, so save ebp and scopetable offset
+ push esi
+ push ebp
+
+ lea ebp, FRAME_EBP_OFFSET[ebx]
+ call [(edi+ecx*4).filter] ;call the filter
+
+ pop ebp
+ pop esi
+ ;ebx may have been trashed by the filter, so we must reload
+ mov ebx, registration
+
+ ; Accept <0, 0, >0 instead of just -1, 0, +1
+ or eax, eax
+ jz short _lh_continue
+ js short _lh_dismiss
+ ;assert(eax==FILTER_ACCEPT)
+
+ ;reload xscope base, cuz it was trashed by the filter call
+ mov edi, [ebx.scopetable]
+ ;load handler address before we loose components of address mode
+ push ebx ;registration*
+ call __global_unwind2 ;run term handlers
+ add esp, 4
+
+ ;setup ebp for the local unwinder and the specific handler
+ lea ebp, FRAME_EBP_OFFSET[ebx]
+
+ ;the stop try level == accepting except level
+ push esi ;stop try level
+ push ebx ;registration*
+ call __local_unwind2
+ add esp, 8
+
+ lea ecx, [esi+esi*2] ;ecx=trylevel*3
+; set the current trylevel to our enclosing level immediately
+; before giving control to the handler. it is the enclosing
+; level, if any, that guards the handler.
+ mov eax, [(edi+ecx*4).enclosing_level]
+ mov [ebx.trylevel], eax
+ call [(edi+ecx*4).specific_handler] ;call the except handler
+ ;assert(0) ;(NB! should not return)
+
+_lh_continue:
+ ;reload the scope table base, possibly trashed by call to filter
+ mov edi, [ebx.scopetable]
+ lea ecx, [esi+esi*2]
+ mov esi, [edi+ecx*4+0] ;load the enclosing trylevel
+ jmp short _lh_top
+
+_lh_dismiss:
+ mov eax, DISPOSITION_DISMISS ;dismiss the exception
+ jmp short _lh_return
+
+_lh_bagit:
+ mov eax, DISPOSITION_CONTINUE_SEARCH
+ jmp short _lh_return
+
+_lh_unwinding:
+ push ebp
+ lea ebp, FRAME_EBP_OFFSET[ebx]
+ push -1
+ push ebx
+ call __local_unwind2
+ add esp, 8
+ pop ebp
+ ;the return value is not really relevent in an unwind context
+ mov eax, DISPOSITION_CONTINUE_SEARCH
+
+_lh_return:
+cEnd
+
+public __seh_longjmp_unwind@4
+__seh_longjmp_unwind@4 proc near
+ push ebp
+ mov ecx, 8[esp]
+ mov ebp, [ecx.saved_ebp]
+ mov eax, [ecx.saved_trylevel]
+ push eax
+ mov eax, [ecx.saved_xregistration]
+ push eax
+ call __local_unwind2
+ add esp, 8
+ pop ebp
+ ret 4
+__seh_longjmp_unwind@4 endp
+
+EndCODE
+END