	INCLUDE	inc.i
	
;
; vfork for MiNT. Note that the return address must be popped off the stack,
; or else it could be clobbered by the child and the parent would be left
; returning to la-la land. Also note that MiNT guarantees that register a1
; will be preserved across a vfork() system call.
;

	FUDATA
_store:		ds.l	32

	INFO
	xref	___mint		; MiNT version kept here
	xref	_errno
L_vfsav:	dc.l	_store

	CODE
	IF	_REGARG
	xdef	@vfork
	xref	@tfork
@vfork:
	ELSE
	xdef	_vfork
	xref	_tfork
_vfork:
	ENDC
	
	move.l	(sp)+,a1	; save return address; this is important!
	IF	_SHORT
	tst.w	___mint
	ELSE
	tst.l	___mint
	ENDC
	beq.s	L_TOS		; go do the TOS thing
	move.w	#$113,-(sp)	; push MiNT Pvfork() parameter
	trap	#1		; Vfork
	addq.l	#2,sp
	tst.l	d0		; error??
	bmi	L_err
	jmp	(a1)		; return
L_TOS:
	lea		L_vfsav,a0
	movem.l	d2-d7/a1-a6,(a0)	; save registers - in _store
	IF	_REGARG
	move.l	a0,d0
	lea	L_newprog,a0
	bsr	@tfork
	ELSE
	move.l	a0,-(sp)
	pea	L_newprog
	bsr	_tfork		; tfork(L_newprog,*L_vfsav)
	addq.l	#8,sp
	ENDC
	lea		L_vfsav,a0
	movem.l	(a0),d2-d7/a1-a6	; restore reggies
	tst.l	d0		; fork went OK??
	bmi.s	L_err		; no -- error
	jmp	(a1)		; return to caller
L_err:
	IF	_SHORT
	neg.w	d0
	move.w	d0,_errno
	ELSE
	neg.l	d0
	move.l	d0,_errno	; save error code in errno
	ENDC
	moveq.l	#-1,d0		; return -1
	jmp	(a1)		; return

;
; L_newprog: here is where the child starts executing,with argument
; L_vfsav. We restore registers,zero d0, and jump back to parent
;

L_newprog:
	addq.l	#4,sp		; pop useless return address
	IF	_REGARG
	move.l	d0,a0
	ELSE
	move.l	(sp)+,a0	; get address of save area
	ENDC
	movem.l	(a0),d2-d7/a1-a6	; restore reggies
	moveq	#$0,d0		; child always returns 0 from vfork
	jmp	(a1)		; back to caller, as child process
	end
