	INCLUDE	inc.i
	
	INFO

	xref	___mint
	xref	__sigmask

;
; setjmp.cpp 
;
	CODE

	IF	_REGARG
	xdef	@setjmp
	xdef	@longjmp
	xdef	@sigsetjmp
	xdef	@siglongjmp
	ELSE
	xdef	_setjmp
	xdef	_longjmp
	xdef	_sigsetjmp
	xdef	_siglongjmp
	ENDC

	; sigsetjmp(sigjmp_buf env, int savemask)
	; address of sigjmp_buf will be in a0
	; savemask will be in d0/a1 (signextended)
	IF	_REGARG
@sigsetjmp:
	IF	_SHORT
	ext.l	d0
	ENDC
	move.l	d0,52(a0)		; save sigmask for siglongjmp?
	ELSE
_sigsetjmp:
	move.l	4(sp),a0		
	IF	_SHORT
	move.w	8(sp),a1
	ELSE
	move.l	8(sp),a1
	ENDC
	move.l	a1,52(a0)		; save sigmask for siglongjmp?
	ENDC
	
	beq.w	Common			; no -- call common code
	
	move.l	__sigmask,d0		; save tos emulation signal mask
	; see if MiNT is active
	IF	_SHORT
	tst.w	___mint
	ELSE
	tst.l	___mint
	ENDC
	beq.w	SSJ_nomint		; no -- skip Psigblock
	clr.l	-(sp)			; add no signals to sigmask
	move.w	#$116,-(sp)		; Psigblock() system call
	trap	#1
	addq	#6,sp

SSJ_nomint:
	bset	#0,d0			; make it != 0 (SIGNULL is unmaskable)
	move.l	d0,52(a0)		; save signal mask
	bra	Common			; call code common with setjmp


	; setjmp(sigjmp_buf env)
	; address of jmp_buf will be in a0
	IF	_REGARG
@setjmp:
	ELSE
_setjmp:
	move.l	4(sp),a0
	ENDC
	
	clr.l	52(a0)			; do not restore sigmask on longjmp
Common:
	move.l	(sp),(a0)		; save return address
	movem.l	d2-d7/a2-a7,4(a0)	; save registers d2-d7/a2-a7
	moveq	#0,d0			; return value is 0
	rts


	; siglongjmp(sigjmpbuf env, int retval)
	; longjmp(sigjmpbuf env, int retval)
	IF	_REGARG
@longjmp:
@siglongjmp:
	ELSE
_longjmp:
_siglongjmp:
	ENDC
	; see if MiNT is active
	IF	_SHORT
	tst.w	___mint	
	ELSE
	tst.l	___mint
	ENDC
	
	beq.w	LJ_nomint		; no -- do not call Psigreturn
	
	IF	_REGARG			; save d0,a0 before Psigreturn
	IF	_SHORT
	move.w	d0,-(sp)
	ELSE
	move.l	d0,-(sp)
	ENDC
	move.l	a0,-(sp)
	ENDC
	move.w	#$11a,-(sp)		; Psigreturn() system call
	trap	#1			; (ignored if not in a sig handler)
	addq.w	#2,sp
	
LJ_nomint:
	; address of jmpbuf in a0
	IF	_REGARG
	move.l	(sp),a0
	ELSE
	move.l	4(sp),a0		
	ENDC
	
	move.l	52(a0),d0		; want to restore sigmask?
	beq.w	Norestore		; no -- skip restore code
	bclr	#0,d0			; dump SIGNUL
	move.l	d0,__sigmask		; restore tos emulation signal mask
	
	; see if MiNT is active
	IF	_SHORT
	tst.w	___mint
	ELSE
	tst.l	___mint
	ENDC
	beq.w	Norestore		; no -- do not call Psigblock
	move.l	d0,-(sp)		; add no signals to sigmask
	move.w	#$117,-(sp)		; Psigblock() system call
	trap	#1
	addq	#6,sp
	move.l	(sp),a0			; restore a0 == jmpbuf

Norestore:
	; value to return in d0 ...
	IF	_REGARG
	IF	_SHORT
	move.w	4(sp),d0
	ELSE
	move.l	4(sp),d0
	ENDC
	ELSE
	IF	_SHORT
	move.w	8(sp),d0
	ELSE
	move.l	8(sp),d0
	ENDC
	ENDC
	
	bne.w	L1			; ... may not be 0
	moveq	#1,d0
L1:
	movem.l	4(a0),d2-d7/a2-a7	; restore saved reggies
	move.l	(a0),(sp)		; and the saved return address
	rts				; will restore a7
	end
