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