/* $NetBSD: _context_u.S,v 1.5 2004/07/10 20:57:00 nathanw Exp $ */ /* * Copyright (c) 2001 Wasabi Systems, Inc. * All rights reserved. * * Written by Allen Briggs 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 "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. */ /* * According to the SVR4 ABI for PPC, r1, r14-r31, LR, and portions of the * CR are non-volatile. I.e., they need to be preserved across the function * call. * * If _getcontext_u is called, set the UC_USER_BIT in the UC_FLAGS. If * _setcontext_u sees that bit, then it will just restore this part of the * context, otherwise, it will call through to setcontext(2). */ /* * Arrange to not include FP save/restore on a soft-float * build. Thread switching shouldn't consume 40 system traps. */ #ifdef _SOFT_FLOAT #define FPUFLAG 0 #define GETFP(reg) #define SETFP #else #define FPUFLAG _UC_FPU #define GETFP(reg) \ mffs %r0 ; \ stfd %r0, (_REG_FPSCR - 4)(reg) ; \ stfd %r14, (_REG_FP0 + 14*8)(reg) ; \ stfd %r15, (_REG_FP0 + 15*8)(reg) ; \ stfd %r16, (_REG_FP0 + 16*8)(reg) ; \ stfd %r17, (_REG_FP0 + 17*8)(reg) ; \ stfd %r18, (_REG_FP0 + 18*8)(reg) ; \ stfd %r19, (_REG_FP0 + 19*8)(reg) ; \ stfd %r20, (_REG_FP0 + 20*8)(reg) ; \ stfd %r21, (_REG_FP0 + 21*8)(reg) ; \ stfd %r22, (_REG_FP0 + 22*8)(reg) ; \ stfd %r23, (_REG_FP0 + 23*8)(reg) ; \ stfd %r24, (_REG_FP0 + 24*8)(reg) ; \ stfd %r25, (_REG_FP0 + 25*8)(reg) ; \ stfd %r26, (_REG_FP0 + 26*8)(reg) ; \ stfd %r27, (_REG_FP0 + 27*8)(reg) ; \ stfd %r28, (_REG_FP0 + 28*8)(reg) ; \ stfd %r29, (_REG_FP0 + 29*8)(reg) ; \ stfd %r30, (_REG_FP0 + 30*8)(reg) ; \ stfd %r31, (_REG_FP0 + 31*8)(reg) #define SETFP \ andi. %r5, %r3, _UC_FPU ; \ beq 1f ; \ ; \ lwz %r5, (_UC_FPVALID)(%r4) ; \ or. %r5, %r5, %r5 ; \ beq 1f ; \ ; \ lfd %r14, (_REG_FP0 + 14*8)(%r4) ; \ lfd %r15, (_REG_FP0 + 15*8)(%r4) ; \ lfd %r16, (_REG_FP0 + 16*8)(%r4) ; \ lfd %r17, (_REG_FP0 + 17*8)(%r4) ; \ lfd %r18, (_REG_FP0 + 18*8)(%r4) ; \ lfd %r19, (_REG_FP0 + 19*8)(%r4) ; \ lfd %r20, (_REG_FP0 + 20*8)(%r4) ; \ lfd %r21, (_REG_FP0 + 21*8)(%r4) ; \ lfd %r22, (_REG_FP0 + 22*8)(%r4) ; \ lfd %r23, (_REG_FP0 + 23*8)(%r4) ; \ lfd %r24, (_REG_FP0 + 24*8)(%r4) ; \ lfd %r25, (_REG_FP0 + 25*8)(%r4) ; \ lfd %r26, (_REG_FP0 + 26*8)(%r4) ; \ lfd %r27, (_REG_FP0 + 27*8)(%r4) ; \ lfd %r28, (_REG_FP0 + 28*8)(%r4) ; \ lfd %r29, (_REG_FP0 + 29*8)(%r4) ; \ lfd %r30, (_REG_FP0 + 30*8)(%r4) ; \ lfd %r31, (_REG_FP0 + 31*8)(%r4) ; \ lfd %r0, (_REG_FPSCR - 4)(%r4) ; \ mtfsf 0xff, %r0 ; \ 1: #endif #define GETC(reg) \ stw %r1, (_REG_R0 + 1*4)(reg) ; \ stmw %r14, (_REG_R0 + 14*4)(reg) ; \ mfcr %r0 ; \ stw %r0, _REG_CR(reg) ; \ mflr %r0 ; \ stw %r0, _REG_LR(reg) ; \ stw %r0, _REG_PC(reg) ; \ ; \ GETFP(reg) ; \ ; \ li %r8, 1 ; \ stw %r8, (_UC_FPVALID)(reg) ; \ slwi %r9, %r8, _UC_USER_BIT ; \ ori %r9, %r9, (_UC_CPU | FPUFLAG) ; \ stw %r9, (UC_FLAGS)(reg) #define SETC \ li %r9, 1 ; \ slwi %r9, %r9, _UC_USER_BIT ; \ lwz %r3, (UC_FLAGS)(%r4) ; \ and. %r9, %r3, %r9 ; \ beq 2f ; \ ; \ lwz %r1, (_REG_R0 + 1*4)(%r4) ; \ lmw %r14, (_REG_R0 + 14*4)(%r4) ; \ lwz %r0, _REG_LR(%r4) ; \ mtlr %r0 ; \ lwz %r0, _REG_PC(%r4) ; \ mtctr %r0 ; \ ; \ SETFP ; \ ; \ lwz %r0, _REG_CR(%r4) ; \ mtcr %r0 ; \ bctr ; \ 2: ; \ mr %r3, %r4 ; \ b PIC_PLT(_C_LABEL(setcontext)) ; \ /* NOTREACHED */ ENTRY(_getcontext_u) GETC(%r3) xor %r3,%r3,%r3 blr ENTRY(_setcontext_u) mr %r4,%r3 SETC ENTRY(_swapcontext_u) GETC(%r3) SETC