178 lines
5.7 KiB
NASM
178 lines
5.7 KiB
NASM
|
;*****************************************************************************
|
||
|
;*
|
||
|
;* Open Watcom Project
|
||
|
;*
|
||
|
;* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
|
||
|
;*
|
||
|
;* ========================================================================
|
||
|
;*
|
||
|
;* This file contains Original Code and/or Modifications of Original
|
||
|
;* Code as defined in and that are subject to the Sybase Open Watcom
|
||
|
;* Public License version 1.0 (the 'License'). You may not use this file
|
||
|
;* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
|
||
|
;* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
|
||
|
;* provided with the Original Code and Modifications, and is also
|
||
|
;* available at www.sybase.com/developer/opensource.
|
||
|
;*
|
||
|
;* The Original Code and all software distributed under the License are
|
||
|
;* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||
|
;* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
|
||
|
;* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
|
||
|
;* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
|
||
|
;* NON-INFRINGEMENT. Please see the License for the specific language
|
||
|
;* governing rights and limitations under the License.
|
||
|
;*
|
||
|
;* ========================================================================
|
||
|
;*
|
||
|
;* Description: C library setjmp/longjmp support for 386 processors
|
||
|
;*
|
||
|
;*****************************************************************************
|
||
|
|
||
|
.386p
|
||
|
include mdef.inc
|
||
|
include struct.inc
|
||
|
|
||
|
codeptr "C",__longjmp_handler
|
||
|
|
||
|
modstart setjmp
|
||
|
|
||
|
ifdef __386__
|
||
|
ifdef __OS2__
|
||
|
xref DosUnwindException
|
||
|
endif
|
||
|
endif
|
||
|
ifdef __NT__
|
||
|
xref _RtlUnwind@16
|
||
|
endif
|
||
|
|
||
|
xdefp "C",_setjmp
|
||
|
defpe _setjmp
|
||
|
mov [eax],ebx ; save registers
|
||
|
mov 4[eax],ecx
|
||
|
mov 8[eax],edx
|
||
|
mov 12[eax],esi
|
||
|
mov 16[eax],edi
|
||
|
mov 20[eax],ebp
|
||
|
pop 24[eax] ; get return address
|
||
|
mov 28[eax],esp
|
||
|
push 24[eax] ; push return address back on stack
|
||
|
mov 32[eax],es ; save segment registers
|
||
|
mov 34[eax],ds
|
||
|
mov 36[eax],cs
|
||
|
mov 38[eax],fs
|
||
|
mov 40[eax],gs
|
||
|
mov 42[eax],ss
|
||
|
ifdef __NT__
|
||
|
push fs:[0] ; touched this line to cause recompile
|
||
|
pop 44[eax]
|
||
|
endif
|
||
|
ifdef __386__
|
||
|
ifdef __OS2__
|
||
|
push fs:[0] ; get exception chain
|
||
|
pop 44[eax] ; ...
|
||
|
endif
|
||
|
endif
|
||
|
sub eax,eax ; return 0
|
||
|
ret ; return
|
||
|
_setjmp endp
|
||
|
|
||
|
;
|
||
|
; There is a pragma for longjmp, saying that it aborts, therefore
|
||
|
; the code generator does a jmp to here as opposed to a call.
|
||
|
|
||
|
xdefp "C",longjmp
|
||
|
defpe longjmp
|
||
|
ifdef __STACK__
|
||
|
pop eax ; get address of jmp_buf
|
||
|
pop edx ; get return code
|
||
|
endif
|
||
|
; Warning, warning!
|
||
|
; the profiler knows about the stack frame that longjmp generates.
|
||
|
; do not change these 3 instructions without also changing the findLongJmpStack
|
||
|
; pragma in profilog.c
|
||
|
;
|
||
|
push edx
|
||
|
push eax ; save jmp_buf & retval in safe place
|
||
|
mov ebp,esp
|
||
|
;
|
||
|
; end warning
|
||
|
;
|
||
|
ifdef __NT__
|
||
|
push eax ; save address of jmp_buf
|
||
|
mov eax,[eax+44]
|
||
|
cmp eax,fs:[0]
|
||
|
jne dounwind
|
||
|
jmp short done_unwind
|
||
|
dounwind:
|
||
|
push 0
|
||
|
push offset done_unwind
|
||
|
push eax ; unwind up to but not including SEH active
|
||
|
; at setjmp()
|
||
|
call _RtlUnwind@16 ; trashes most registers except for ebp
|
||
|
done_unwind:
|
||
|
mov esp,ebp
|
||
|
mov eax,0[ebp]
|
||
|
mov edx,4[ebp]
|
||
|
endif
|
||
|
ifdef __386__
|
||
|
ifdef __OS2__
|
||
|
push eax ; save address of jmp_buf
|
||
|
push 0
|
||
|
;; push offset unwind
|
||
|
mov eax, offset unwind
|
||
|
push eax
|
||
|
mov eax,8[esp]
|
||
|
push 44[eax]
|
||
|
call DosUnwindException
|
||
|
unwind: add esp,12
|
||
|
pop eax ; restore address of jmp_buf
|
||
|
endif
|
||
|
endif
|
||
|
push eax ; save parm regs
|
||
|
push edx
|
||
|
mov dx,42[eax] ; setup old ss:esp as a parm
|
||
|
mov eax,28[eax]
|
||
|
call __longjmp_handler ; call handler
|
||
|
pop edx ; restore parm regs
|
||
|
pop eax
|
||
|
|
||
|
mov ss,42[eax] ; load old ss:esp
|
||
|
mov esp,28[eax] ; ...
|
||
|
push 24[eax] ; push saved eip (our return address)
|
||
|
or edx,edx ; if return code is 0
|
||
|
_if e ; then
|
||
|
inc edx ; - set it to 1
|
||
|
_endif ; endif
|
||
|
push edx ; save return code
|
||
|
mov ebx,[eax] ; load up the saved registers
|
||
|
mov ecx,4[eax]
|
||
|
mov esi,12[eax]
|
||
|
mov edi,16[eax]
|
||
|
mov ebp,20[eax]
|
||
|
mov dx,32[eax]
|
||
|
verr dx ; verify segment
|
||
|
_if ne
|
||
|
sub edx,edx
|
||
|
_endif
|
||
|
mov es,dx
|
||
|
mov dx,38[eax]
|
||
|
verr dx ; verify segment
|
||
|
_if ne
|
||
|
sub edx,edx
|
||
|
_endif
|
||
|
mov fs,dx
|
||
|
mov dx,40[eax]
|
||
|
verr dx ; verify segment
|
||
|
_if ne
|
||
|
sub edx,edx
|
||
|
_endif
|
||
|
mov gs,dx
|
||
|
mov edx,8[eax]
|
||
|
mov ds,34[eax]
|
||
|
pop eax ; get return code
|
||
|
ret ; return to point following setjmp call
|
||
|
longjmp endp
|
||
|
|
||
|
_TEXT ends
|
||
|
end
|