summaryrefslogtreecommitdiffstats
path: root/private/crt32/misc/i386/longjmp.asm
diff options
context:
space:
mode:
Diffstat (limited to 'private/crt32/misc/i386/longjmp.asm')
-rw-r--r--private/crt32/misc/i386/longjmp.asm150
1 files changed, 150 insertions, 0 deletions
diff --git a/private/crt32/misc/i386/longjmp.asm b/private/crt32/misc/i386/longjmp.asm
new file mode 100644
index 000000000..ae236afff
--- /dev/null
+++ b/private/crt32/misc/i386/longjmp.asm
@@ -0,0 +1,150 @@
+;***
+;longjmp.asm
+;
+; Copyright (C) 1994 Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; Contains setjmp(), longjmp() & raisex() routines;
+; split from exsup.asm for granularity purposes.
+;
+;Notes:
+;
+;Revision History:
+; 01-12-94 PML Split from setjmp.asm, added C9.0 generic EH
+; callback for unwind.
+;
+;*******************************************************************************
+
+;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
+
+.xlist
+include pversion.inc
+?DFDATA = 1
+?NODATA = 1
+include cmacros.mas
+include exsup.inc
+.list
+
+BeginDATA
+
+COMM __setjmpexused:dword
+
+EndDATA
+
+assumes DS,DATA
+assumes FS,DATA
+
+BeginCODE
+if @Version LT 600
+;this needs to go here to work around a masm5 bug. (emits wrong fixup)
+assumes CS,FLAT
+endif
+
+; Following symbols defined in exsup.asm, sehsupp.c
+extrn __except_list:near
+extrn __global_unwind2:near
+extrn __local_unwind2:near
+extrn __rt_probe_read4@4:near
+
+; int
+; longjmp (
+; IN jmp_buf env
+; IN int val)
+;
+; Routine Description:
+;
+; Restore the stack and register environment saved by _setjmp.
+; Reloads callee-save registers and stack pointer to that saved in
+; the jmp_buf, then returns to the point of the _setjmp call.
+;
+; If exception unwinding is enabled, also reload the exception state
+; from the jmp_buf by doing an unwind (both global and local) back
+; to the old state. Do so by checking for a new-format (C9.0)
+; jmp_buf, and call the EH longjmp unwinder saved therein if
+; found, else assume a C8.0-vintage jmp_buf and SEH.
+;
+; Arguments:
+;
+; env - Address of the buffer holding the reload state
+; val - Value to return from the _setjmp callsite (if nonzero)
+;
+; Return Value:
+;
+; None. longjmp does not return directly, but instead continues
+; execution from the point of the _setjmp used to initialize the
+; jmp_buf. That call will return the 'val' parameter if nonzero,
+; else a one.
+
+cProc longjmp,<C,PUBLIC>
+cBegin
+ mov ebx, [esp+4] ;get jmp_buf
+
+ ;restore ebp before possible call to local_unwind-er
+ ; the call to global/local unwind will preserve this (callee save).
+ mov ebp, [ebx.saved_ebp] ;set up bp
+ifdef _NTSDK
+ cmp __setjmpexused, 0
+ je short _lj_no_unwind
+endif
+ mov esi, [ebx.saved_xregistration]
+ cmp esi, dword ptr fs:__except_list
+ je short _lj_local_unwind
+
+ push esi
+ call __global_unwind2
+ add esp,4
+
+_lj_local_unwind:
+ cmp esi, 0
+ je short _lj_no_unwind
+
+ ; Check if called with old or new format jmp_buf. Look for the
+ ; version cookie that's only present in the new format.
+ lea eax, [ebx.version_cookie]
+ push eax
+ call __rt_probe_read4@4
+ or eax, eax
+ jz short _lj_old_unwind
+ mov eax, [ebx.version_cookie]
+ cmp eax, JMPBUF_COOKIE
+ jnz short _lj_old_unwind
+
+ ; Called with a new-format jmp_buf. Call unwind function supplied
+ ; to the jmp_buf at setjmp time.
+ mov eax, [ebx.unwind_func]
+ or eax, eax
+ jz short _lj_no_unwind ;no local unwind necessary
+ push ebx
+ call eax
+ jmp short _lj_no_unwind
+
+ ; Called with an old-format jmp_buf. Duplicate old longjmp behavior,
+ ; assuming there's a C8.0 SEH node at top.
+_lj_old_unwind:
+ mov eax, [ebx.saved_trylevel]
+ push eax
+ push esi
+ call __local_unwind2
+ add esp, 8
+
+_lj_no_unwind:
+ mov edx, ebx
+ mov ebx, [edx.saved_ebx] ;recover registers...
+ mov edi, [edx.saved_edi]
+ mov esi, [edx.saved_esi]
+
+ mov eax, [esp+8] ;load the return value
+ cmp eax, 1 ;make sure it's not 0
+ adc eax, 0
+
+ mov esp, [edx.saved_esp] ;here, sp gets scorched
+ add esp, 4 ;punt the (old) return address
+ jmp [edx.saved_return] ;return
+cEnd
+
+EndCODE
+END