Blame sysdeps/unix/sysv/linux/m68k/m680x0/makecontext.S

Packit 6c4009
/* Create new context.
Packit 6c4009
   Copyright (C) 2012-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <sysdep.h>
Packit 6c4009
Packit 6c4009
#include "ucontext_i.h"
Packit 6c4009
Packit 6c4009
Packit 6c4009
ENTRY(__makecontext)
Packit 6c4009
	move.l	4(%sp), %a0
Packit 6c4009
Packit 6c4009
	/* Get the address of the function we are supposed to run.  */
Packit 6c4009
	move.l	8(%sp), oPC(%a0)
Packit 6c4009
Packit 6c4009
	/* Compute the address of the stack.  The information comes from
Packit 6c4009
	   to us_stack element.  */
Packit 6c4009
	move.l	oSS_SP(%a0), %a1
Packit 6c4009
	add.l	oSS_SIZE(%a0), %a1
Packit 6c4009
Packit 6c4009
	/* Remember the number of parameters for the exit handler since
Packit 6c4009
	   it has to remove them.  We store the number in the D7 register
Packit 6c4009
	   which the function we will call must preserve.  */
Packit 6c4009
	move.l	12(%sp), %d1
Packit 6c4009
	move.l	%d1, oGREGS+7*4(%a0)
Packit 6c4009
Packit 6c4009
	/* Make room on the new stack for the parameters.
Packit 6c4009
	   Room for the arguments, return address (== 1f) and
Packit 6c4009
	   oLINK pointer is needed.  */
Packit 6c4009
	neg.l	%d1
Packit 6c4009
	lea	-8(%a1,%d1.l*4), %a1
Packit 6c4009
	neg.l	%d1
Packit 6c4009
Packit 6c4009
	/* Store the future stack pointer.  */
Packit 6c4009
	move.l	%a1, oSP(%a0)
Packit 6c4009
Packit 6c4009
	/* Put the next context on the new stack (from the uc_link
Packit 6c4009
	   element).  */
Packit 6c4009
	move.l	oLINK(%a0), 4(%a1,%d1.l*4)
Packit 6c4009
Packit 6c4009
	/* Copy all the parameters.  */
Packit 6c4009
1:	subq.l	#1,%d1
Packit 6c4009
	jmi	2f
Packit 6c4009
	move.l	16(%sp,%d1.l*4), 4(%a1,%d1.l*4)
Packit 6c4009
	jra	1b
Packit 6c4009
2:
Packit 6c4009
Packit 6c4009
	/* If the function we call returns we must continue with the
Packit 6c4009
	   context which is given in the uc_link element.  To do this
Packit 6c4009
	   set the return address for the function the user provides
Packit 6c4009
	   to a little bit of helper code which does the magic (see
Packit 6c4009
	   below).  */
Packit 6c4009
	lea	1f(%pc), %a0
Packit 6c4009
	move.l	%a0, (%a1)
Packit 6c4009
	/* 'makecontext' returns no value.  */
Packit 6c4009
	rts
Packit 6c4009
Packit 6c4009
	/* This is the helper code which gets called if a function which
Packit 6c4009
	   is registered with 'makecontext' returns.  In this case we
Packit 6c4009
	   have to install the context listed in the uc_link element of
Packit 6c4009
	   the context 'makecontext' manipulated at the time of the
Packit 6c4009
	   'makecontext' call.  If the pointer is NULL the process must
Packit 6c4009
	   terminate.
Packit 6c4009
	   Make sure to separate the return label from the previous unwind
Packit 6c4009
	   region, because the unwinder uses ra-1 to find the FDE.  */
Packit 6c4009
	cfi_endproc
Packit 6c4009
	nop
Packit 6c4009
1:
Packit 6c4009
	/* This removes the parameters passed to the function given to
Packit 6c4009
	   'makecontext' from the stack.  D7 contains the number of
Packit 6c4009
	   parameters (see above).  */
Packit 6c4009
	lea	(%sp,%d7.l*4), %sp
Packit 6c4009
Packit 6c4009
	tst.l	(%sp)			/* Check the next context.  */
Packit 6c4009
	jeq	2f			/* If it is zero exit.  */
Packit 6c4009
Packit 6c4009
	jbsr	JUMPTARGET(__setcontext)
Packit 6c4009
	/* If this returns (which can happen if the syscall fails) we'll
Packit 6c4009
	   exit the program with the return error value (-1).  */
Packit 6c4009
Packit 6c4009
	move.l	%d0, (%sp)
Packit 6c4009
2:	jbsr	HIDDEN_JUMPTARGET(exit)
Packit 6c4009
	/* The 'exit' call should never return.  In case it does cause
Packit 6c4009
	   the process to terminate.  */
Packit 6c4009
	illegal
Packit 6c4009
	cfi_startproc
Packit 6c4009
END(__makecontext)
Packit 6c4009
Packit 6c4009
weak_alias (__makecontext, makecontext)