xref: /netbsd-src/lib/libc/arch/hppa/gen/makecontext.c (revision d66dab05c4e6f8d1676ef226f497770da752d099)
1*d66dab05Sskrll /*	$NetBSD: makecontext.c,v 1.6 2012/03/22 12:31:32 skrll Exp $	*/
256371a56Schs 
356371a56Schs /*-
456371a56Schs  * Copyright (c) 2001 The NetBSD Foundation, Inc.
556371a56Schs  * All rights reserved.
656371a56Schs  *
756371a56Schs  * This code is derived from software contributed to The NetBSD Foundation
856371a56Schs  * by Klaus Klein.
956371a56Schs  *
1056371a56Schs  * Redistribution and use in source and binary forms, with or without
1156371a56Schs  * modification, are permitted provided that the following conditions
1256371a56Schs  * are met:
1356371a56Schs  * 1. Redistributions of source code must retain the above copyright
1456371a56Schs  *    notice, this list of conditions and the following disclaimer.
1556371a56Schs  * 2. Redistributions in binary form must reproduce the above copyright
1656371a56Schs  *    notice, this list of conditions and the following disclaimer in the
1756371a56Schs  *    documentation and/or other materials provided with the distribution.
1856371a56Schs  *
1956371a56Schs  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2056371a56Schs  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2156371a56Schs  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2256371a56Schs  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2356371a56Schs  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2456371a56Schs  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2556371a56Schs  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2656371a56Schs  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2756371a56Schs  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2856371a56Schs  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2956371a56Schs  * POSSIBILITY OF SUCH DAMAGE.
3056371a56Schs  */
3156371a56Schs 
3256371a56Schs #include <sys/cdefs.h>
3356371a56Schs #if defined(LIBC_SCCS) && !defined(lint)
34*d66dab05Sskrll __RCSID("$NetBSD: makecontext.c,v 1.6 2012/03/22 12:31:32 skrll Exp $");
3556371a56Schs #endif
3656371a56Schs 
3756371a56Schs #include <inttypes.h>
3856371a56Schs #include <stddef.h>
3956371a56Schs #include <ucontext.h>
4056371a56Schs #include "extern.h"
4156371a56Schs 
4256371a56Schs #include <stdarg.h>
4356371a56Schs 
4456371a56Schs #include <sys/types.h>
4556371a56Schs #include <machine/frame.h>
4656371a56Schs 
4739079c5fSjoerg void __resumecontext(void) __dead;
4839079c5fSjoerg 
4956371a56Schs void
makecontext(ucontext_t * ucp,void (* func)(void),int argc,...)5056371a56Schs makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
5156371a56Schs {
5256371a56Schs 	__greg_t *gr = ucp->uc_mcontext.__gregs;
5356371a56Schs 	__greg_t *gp, rp, fp;
54f05974f4Sperry 	register __greg_t dp __asm("r27");
5556371a56Schs 	uintptr_t *sp;
5656371a56Schs 	int i;
5756371a56Schs 	va_list ap;
5856371a56Schs 
5956371a56Schs 	/* LINTED uintptr_t is safe */
6056371a56Schs 	sp  = (uintptr_t *)ucp->uc_stack.ss_sp;
6156371a56Schs 	/* LINTED uintptr_t is safe */
6256371a56Schs 	sp += 16;			/* standard frame */
6356371a56Schs 	sp += (argc >= 4 ? argc : 4);	/* Make room for >=4 arguments. */
6456371a56Schs 	sp  = (uintptr_t *)
6556371a56Schs 	      ((uintptr_t)(sp + 16) & ~0x3f);	/* Align on 64-byte boundary. */
6656371a56Schs 
6756371a56Schs 	/* Save away the registers that we'll need. */
6856371a56Schs 	gr[_REG_SP] = (__greg_t)sp;
6956371a56Schs 	rp = (__greg_t)__resumecontext;
7056371a56Schs 	if (rp & 2) {
7156371a56Schs 		gp = (__greg_t *)(rp & ~3);
7256371a56Schs 		rp = gp[0];
7356371a56Schs 		sp[-8] = gp[1];
7456371a56Schs 	}
7556371a56Schs 	gr[_REG_RP] = rp;
7656371a56Schs 	fp = (__greg_t)func;
7756371a56Schs 	if (fp & 2) {
7856371a56Schs 		gp = (__greg_t *)(fp & ~3);
7956371a56Schs 		fp = gp[0];
8056371a56Schs 		gr[_REG_R19] = gp[1];
8156371a56Schs 	}
8256371a56Schs 	gr[_REG_PCOQH] = fp | HPPA_PC_PRIV_USER;
8356371a56Schs 	gr[_REG_PCOQT] = (fp + 4) | HPPA_PC_PRIV_USER;
84*d66dab05Sskrll 	/* LINTED dp is reg27, ref. above, so initialized */
8556371a56Schs 	gr[_REG_DP] = dp;
8656371a56Schs 
8756371a56Schs 	/* Construct argument list. */
8856371a56Schs 	va_start(ap, argc);
8956371a56Schs 	/* Up to the first four arguments are passed in %arg0-3. */
9056371a56Schs 	for (i = 0; i < argc && i < 4; i++) {
9156371a56Schs 		/* LINTED uintptr_t is safe */
9256371a56Schs 		gr[_REG_ARG0 - i] = va_arg(ap, uintptr_t);
9356371a56Schs 	}
9456371a56Schs 	/* Pass remaining arguments on the stack below the %arg0-3 gap. */
9556371a56Schs 	for (; i < argc; i++) {
9656371a56Schs 		/* LINTED uintptr_t is safe */
9756371a56Schs 		sp[-9 - i] = va_arg(ap, uintptr_t);
9856371a56Schs 	}
9956371a56Schs 	va_end(ap);
10056371a56Schs }
101