1*2fe8fb19SBen Gras /* $NetBSD: makecontext.c,v 1.5 2009/12/14 01:07:42 matt Exp $ */ 2*2fe8fb19SBen Gras 3*2fe8fb19SBen Gras /*- 4*2fe8fb19SBen Gras * Copyright (c) 2001 The NetBSD Foundation, Inc. 5*2fe8fb19SBen Gras * All rights reserved. 6*2fe8fb19SBen Gras * 7*2fe8fb19SBen Gras * This code is derived from software contributed to The NetBSD Foundation 8*2fe8fb19SBen Gras * by Klaus Klein. 9*2fe8fb19SBen Gras * 10*2fe8fb19SBen Gras * Redistribution and use in source and binary forms, with or without 11*2fe8fb19SBen Gras * modification, are permitted provided that the following conditions 12*2fe8fb19SBen Gras * are met: 13*2fe8fb19SBen Gras * 1. Redistributions of source code must retain the above copyright 14*2fe8fb19SBen Gras * notice, this list of conditions and the following disclaimer. 15*2fe8fb19SBen Gras * 2. Redistributions in binary form must reproduce the above copyright 16*2fe8fb19SBen Gras * notice, this list of conditions and the following disclaimer in the 17*2fe8fb19SBen Gras * documentation and/or other materials provided with the distribution. 18*2fe8fb19SBen Gras * 19*2fe8fb19SBen Gras * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20*2fe8fb19SBen Gras * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21*2fe8fb19SBen Gras * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22*2fe8fb19SBen Gras * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23*2fe8fb19SBen Gras * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24*2fe8fb19SBen Gras * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25*2fe8fb19SBen Gras * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26*2fe8fb19SBen Gras * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27*2fe8fb19SBen Gras * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28*2fe8fb19SBen Gras * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29*2fe8fb19SBen Gras * POSSIBILITY OF SUCH DAMAGE. 30*2fe8fb19SBen Gras */ 31*2fe8fb19SBen Gras 32*2fe8fb19SBen Gras #include <sys/cdefs.h> 33*2fe8fb19SBen Gras #if defined(LIBC_SCCS) && !defined(lint) 34*2fe8fb19SBen Gras __RCSID("$NetBSD: makecontext.c,v 1.5 2009/12/14 01:07:42 matt Exp $"); 35*2fe8fb19SBen Gras #endif 36*2fe8fb19SBen Gras 37*2fe8fb19SBen Gras #include <inttypes.h> 38*2fe8fb19SBen Gras #include <stddef.h> 39*2fe8fb19SBen Gras #include <ucontext.h> 40*2fe8fb19SBen Gras #include "extern.h" 41*2fe8fb19SBen Gras 42*2fe8fb19SBen Gras #include <stdarg.h> 43*2fe8fb19SBen Gras 44*2fe8fb19SBen Gras void 45*2fe8fb19SBen Gras makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) 46*2fe8fb19SBen Gras { 47*2fe8fb19SBen Gras __greg_t *gr = ucp->uc_mcontext.__gregs; 48*2fe8fb19SBen Gras __greg_t *sp; 49*2fe8fb19SBen Gras int i; 50*2fe8fb19SBen Gras va_list ap; 51*2fe8fb19SBen Gras 52*2fe8fb19SBen Gras void __resumecontext(void); 53*2fe8fb19SBen Gras 54*2fe8fb19SBen Gras /* LINTED uintptr_t is safe */ 55*2fe8fb19SBen Gras sp = (__greg_t *) 56*2fe8fb19SBen Gras ((uintptr_t)ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size); 57*2fe8fb19SBen Gras /* LINTED uintptr_t is safe */ 58*2fe8fb19SBen Gras #if defined(__mips_o32) || defined(__mips_o64) 59*2fe8fb19SBen Gras sp -= (argc >= 4 ? argc : 4); /* Make room for >=4 arguments. */ 60*2fe8fb19SBen Gras sp = (__greg_t *) 61*2fe8fb19SBen Gras ((uintptr_t)sp & ~0x7); /* Align on double-word boundary. */ 62*2fe8fb19SBen Gras #elif defined(__mips_n32) || defined(__mips_n64) 63*2fe8fb19SBen Gras sp -= (argc > 8 ? argc - 8 : 0); /* Make room for > 8 arguments. */ 64*2fe8fb19SBen Gras sp = (__greg_t *) 65*2fe8fb19SBen Gras ((uintptr_t)sp & ~0xf); /* Align on quad-word boundary. */ 66*2fe8fb19SBen Gras #endif 67*2fe8fb19SBen Gras 68*2fe8fb19SBen Gras gr[_REG_SP] = (intptr_t)sp; 69*2fe8fb19SBen Gras gr[_REG_RA] = (intptr_t)__resumecontext; 70*2fe8fb19SBen Gras gr[_REG_T9] = (intptr_t)func; /* required for .abicalls */ 71*2fe8fb19SBen Gras gr[_REG_EPC] = (intptr_t)func; 72*2fe8fb19SBen Gras 73*2fe8fb19SBen Gras /* Construct argument list. */ 74*2fe8fb19SBen Gras va_start(ap, argc); 75*2fe8fb19SBen Gras #if defined(__mips_o32) || defined(__mips_o64) 76*2fe8fb19SBen Gras /* Up to the first four arguments are passed in $a0-3. */ 77*2fe8fb19SBen Gras for (i = 0; i < argc && i < 4; i++) 78*2fe8fb19SBen Gras /* LINTED __greg_t is safe */ 79*2fe8fb19SBen Gras gr[_REG_A0 + i] = va_arg(ap, __greg_t); 80*2fe8fb19SBen Gras /* Pass remaining arguments on the stack above the $a0-3 gap. */ 81*2fe8fb19SBen Gras sp += i; 82*2fe8fb19SBen Gras #endif 83*2fe8fb19SBen Gras #if defined(__mips_n32) || defined(__mips_n64) 84*2fe8fb19SBen Gras /* Up to the first 8 arguments are passed in $a0-7. */ 85*2fe8fb19SBen Gras for (i = 0; i < argc && i < 8; i++) 86*2fe8fb19SBen Gras /* LINTED __greg_t is safe */ 87*2fe8fb19SBen Gras gr[_REG_A0 + i] = va_arg(ap, __greg_t); 88*2fe8fb19SBen Gras /* Pass remaining arguments on the stack above the $a0-3 gap. */ 89*2fe8fb19SBen Gras #endif 90*2fe8fb19SBen Gras /* Pass remaining arguments on the stack above the $a0-3 gap. */ 91*2fe8fb19SBen Gras for (; i < argc; i++) 92*2fe8fb19SBen Gras /* LINTED uintptr_t is safe */ 93*2fe8fb19SBen Gras *sp++ = va_arg(ap, __greg_t); 94*2fe8fb19SBen Gras va_end(ap); 95*2fe8fb19SBen Gras } 96