/* $NetBSD: _context_u.S,v 1.4 2004/08/21 11:31:44 rearnsha Exp $ */ /* * Copyright (c) 2001 Wasabi Systems, Inc. * All rights reserved. * * Written by Jason R. Thorpe for Wasabi Systems, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed for the NetBSD Project by * Wasabi Systems, Inc. * 4. The name of Wasabi Systems, Inc. may not be used to endorse * or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <machine/asm.h> #include <arm/armreg.h> #include "assym.h" /* * Define: * int _getcontext_u(ucontext_t *ctx) * Store the current context in the provided ctx structure. * [only store the callee-saved registers] * int _setcontext_u(const ucontext_t *ctx) * Restore the current context from the provided ctx structure. * int _swapcontext_u(ucontext_t *from_ctx, const ucontext_t *to_ctx) * First, store the current context into from_ctx and then * restore the current context from the to_ctx. */ /* * XXX XXX XXX * XXX Hardware FP context? * XXX Software FP context? * XXX XXX XXX */ /* * NOTE: Clobbers r2. */ #define GETC(reg) \ /* \ * We're only saving the callee-saved registers, here, \ * so make a note of it for SETC() later. \ * \ * And, yes, even if we're only saving callee-saved regs, \ * we need to provide a valid CPSR in case the context is \ * used in a setcontext(2) system call later. (The CPSR \ * is only used in 32-bit mode, and ignored in 26-bit mode.) \ * \ * We play a trick with the PC, here. We don't save the \ * LR (it's caller-save), but we instead stash it in the \ * PC slot in the ucontext so that when the context is \ * resumed, we magically appear back at the call site. \ */ \ mov r2, #(_UC_USER | _UC_CPU) ; \ str r2, [reg, #(UC_FLAGS)] ; \ mov r2, #0 ; \ mrs r2, cpsr /* No-op on 26-bit systems. */ ; \ str r2, [reg, #(_REG_CPSR)] ; \ str lr, [reg, #(_REG_PC)] ; \ add reg, reg, #(_REG_R4) ; \ stmia reg, {r4-r13} /* * NOTE: Clobbers r2. */ #define SETC(reg) \ /* \ * If _UC_USER is set, we only need to restore the \ * callee-saved registers (i.e. we were saved by \ * _getcontext_u(). If it is not set, we need to \ * restore the caller-saved regs, too. \ */ \ ldr r2, [reg, #(UC_FLAGS)] ; \ tst r2, #(_UC_USER) ; \ \ /* _UC_USER case */ ; \ addne reg, reg, #(_REG_R4) ; \ ldmneia reg, {r4-r15} ; \ /* NOTREACHED */ \ \ /* ! _UC_USER case */ \ teq r0, r0 /* set Z */ ; \ teq pc, r15 /* EQ => 32, NE => 26 */ ; \ bne 1f ; \ \ /* 32-bit */ \ ldr r2, [reg, #(_REG_CPSR)] ; \ add reg, reg, #(_REG_R0) ; \ msr cpsr, r2 ; \ ldmia reg, {r0-r15} ; \ /* NOTREACHED */ \ \ 1: /* 26-bit */ \ add reg, reg, #(_REG_R0) ; \ ldmia reg, {r0-r15}^ ; \ /* NOTREACHED */ ENTRY(_getcontext_u) GETC(r0) mov r0, #0x00000000 RET ENTRY(_setcontext_u) SETC(r0) ENTRY(_swapcontext_u) GETC(r0) SETC(r1)