makecontext.c revision 1.5
11.5Sjoerg/* $NetBSD: makecontext.c,v 1.5 2011/09/20 08:42:29 joerg Exp $ */ 21.1Schs 31.1Schs/*- 41.1Schs * Copyright (c) 2001 The NetBSD Foundation, Inc. 51.1Schs * All rights reserved. 61.1Schs * 71.1Schs * This code is derived from software contributed to The NetBSD Foundation 81.1Schs * by Klaus Klein. 91.1Schs * 101.1Schs * Redistribution and use in source and binary forms, with or without 111.1Schs * modification, are permitted provided that the following conditions 121.1Schs * are met: 131.1Schs * 1. Redistributions of source code must retain the above copyright 141.1Schs * notice, this list of conditions and the following disclaimer. 151.1Schs * 2. Redistributions in binary form must reproduce the above copyright 161.1Schs * notice, this list of conditions and the following disclaimer in the 171.1Schs * documentation and/or other materials provided with the distribution. 181.1Schs * 191.1Schs * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 201.1Schs * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 211.1Schs * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 221.1Schs * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 231.1Schs * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 241.1Schs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 251.1Schs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 261.1Schs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 271.1Schs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 281.1Schs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 291.1Schs * POSSIBILITY OF SUCH DAMAGE. 301.1Schs */ 311.1Schs 321.1Schs#include <sys/cdefs.h> 331.1Schs#if defined(LIBC_SCCS) && !defined(lint) 341.5Sjoerg__RCSID("$NetBSD: makecontext.c,v 1.5 2011/09/20 08:42:29 joerg Exp $"); 351.1Schs#endif 361.1Schs 371.1Schs#include <inttypes.h> 381.1Schs#include <stddef.h> 391.1Schs#include <ucontext.h> 401.1Schs#include "extern.h" 411.1Schs 421.1Schs#include <stdarg.h> 431.1Schs 441.1Schs#include <sys/types.h> 451.1Schs#include <machine/frame.h> 461.1Schs 471.5Sjoergvoid __resumecontext(void) __dead; 481.5Sjoerg 491.1Schsvoid 501.1Schsmakecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) 511.1Schs{ 521.1Schs __greg_t *gr = ucp->uc_mcontext.__gregs; 531.1Schs __greg_t *gp, rp, fp; 541.2Sperry register __greg_t dp __asm("r27"); 551.1Schs uintptr_t *sp; 561.1Schs int i; 571.1Schs va_list ap; 581.1Schs 591.1Schs /* LINTED uintptr_t is safe */ 601.1Schs sp = (uintptr_t *)ucp->uc_stack.ss_sp; 611.1Schs /* LINTED uintptr_t is safe */ 621.1Schs sp += 16; /* standard frame */ 631.1Schs sp += (argc >= 4 ? argc : 4); /* Make room for >=4 arguments. */ 641.1Schs sp = (uintptr_t *) 651.1Schs ((uintptr_t)(sp + 16) & ~0x3f); /* Align on 64-byte boundary. */ 661.1Schs 671.1Schs /* Save away the registers that we'll need. */ 681.1Schs gr[_REG_SP] = (__greg_t)sp; 691.1Schs rp = (__greg_t)__resumecontext; 701.1Schs if (rp & 2) { 711.1Schs gp = (__greg_t *)(rp & ~3); 721.1Schs rp = gp[0]; 731.1Schs sp[-8] = gp[1]; 741.1Schs } 751.1Schs gr[_REG_RP] = rp; 761.1Schs fp = (__greg_t)func; 771.1Schs if (fp & 2) { 781.1Schs gp = (__greg_t *)(fp & ~3); 791.1Schs fp = gp[0]; 801.1Schs gr[_REG_R19] = gp[1]; 811.1Schs } 821.1Schs gr[_REG_PCOQH] = fp | HPPA_PC_PRIV_USER; 831.1Schs gr[_REG_PCOQT] = (fp + 4) | HPPA_PC_PRIV_USER; 841.1Schs gr[_REG_DP] = dp; 851.1Schs 861.1Schs /* Construct argument list. */ 871.1Schs va_start(ap, argc); 881.1Schs /* Up to the first four arguments are passed in %arg0-3. */ 891.1Schs for (i = 0; i < argc && i < 4; i++) { 901.1Schs /* LINTED uintptr_t is safe */ 911.1Schs gr[_REG_ARG0 - i] = va_arg(ap, uintptr_t); 921.1Schs } 931.1Schs /* Pass remaining arguments on the stack below the %arg0-3 gap. */ 941.1Schs for (; i < argc; i++) { 951.1Schs /* LINTED uintptr_t is safe */ 961.1Schs sp[-9 - i] = va_arg(ap, uintptr_t); 971.1Schs } 981.1Schs va_end(ap); 991.1Schs} 100