1/* Set current context. 2 Copyright (C) 2009 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 Contributed by Maciej W. Rozycki <macro@codesourcery.com>. 5 6 The GNU C Library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 The GNU C Library is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with the GNU C Library. If not, see 18 <http://www.gnu.org/licenses/>. */ 19 20#include <sysdep.h> 21#include <sys/asm.h> 22#include <sys/fpregdef.h> 23#include <sys/regdef.h> 24 25#include "ucontext_i.h" 26 27/* int setcontext (const ucontext_t *ucp) */ 28 29 .text 30LOCALSZ = 0 31ARGSZ = 0 32MASK = 0x00000000 33#ifdef __PIC__ 34LOCALSZ = 1 /* save gp */ 35#endif 36#if _MIPS_SIM != _ABIO32 37ARGSZ = 1 /* save a0 */ 38# ifdef __PIC__ 39MASK = 0x10000000 40# endif 41#endif 42FRAMESZ = (((ARGSZ + LOCALSZ) * SZREG) + ALSZ) & ALMASK 43GPOFF = FRAMESZ - ((ARGSZ + 1) * SZREG) 44#if _MIPS_SIM != _ABIO32 45A0OFF = FRAMESZ - (1 * SZREG) /* callee-allocated */ 46#else 47A0OFF = FRAMESZ + (0 * SZREG) /* caller-allocated */ 48#endif 49 50NESTED (__setcontext, FRAMESZ, ra) 51 .mask MASK, -(ARGSZ * SZREG) 52 .fmask 0x00000000, 0 53 54#ifdef __PIC__ 55 SETUP_GP 56#endif 57 58 PTR_ADDIU sp, -FRAMESZ 59 60#ifdef __PIC__ 61 SETUP_GP64 (GPOFF, __setcontext) 62 SAVE_GP (GPOFF) 63#endif 64 65 /* Check for the magic flag. */ 66 li v0, 1 67 REG_L v1, (0 * SZREG + MCONTEXT_GREGS)(a0) /* zero */ 68 bne v0, v1, 98f 69 70 REG_S a0, A0OFF(sp) 71 72/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, NULL, _NSIG8) */ 73 li a3, _NSIG8 74 move a2, zero 75 PTR_ADDU a1, a0, UCONTEXT_SIGMASK 76 li a0, SIG_SETMASK 77 78 li v0, SYS_ify (rt_sigprocmask) 79 syscall 80 bnez a3, 99f 81 82 REG_L v0, A0OFF(sp) 83 84#ifdef __mips_hard_float 85# if _MIPS_SIM == _ABI64 86 l.d fs0, (24 * SZREG + MCONTEXT_FPREGS)(v0) 87 l.d fs1, (25 * SZREG + MCONTEXT_FPREGS)(v0) 88 l.d fs2, (26 * SZREG + MCONTEXT_FPREGS)(v0) 89 l.d fs3, (27 * SZREG + MCONTEXT_FPREGS)(v0) 90 l.d fs4, (28 * SZREG + MCONTEXT_FPREGS)(v0) 91 l.d fs5, (29 * SZREG + MCONTEXT_FPREGS)(v0) 92 l.d fs6, (30 * SZREG + MCONTEXT_FPREGS)(v0) 93 l.d fs7, (31 * SZREG + MCONTEXT_FPREGS)(v0) 94 95# else /* _MIPS_SIM != _ABI64 */ 96 l.d fs0, (20 * SZREG + MCONTEXT_FPREGS)(v0) 97 l.d fs1, (22 * SZREG + MCONTEXT_FPREGS)(v0) 98 l.d fs2, (24 * SZREG + MCONTEXT_FPREGS)(v0) 99 l.d fs3, (26 * SZREG + MCONTEXT_FPREGS)(v0) 100 l.d fs4, (28 * SZREG + MCONTEXT_FPREGS)(v0) 101 l.d fs5, (30 * SZREG + MCONTEXT_FPREGS)(v0) 102 103# endif /* _MIPS_SIM != _ABI64 */ 104 105 lw v1, MCONTEXT_FPC_CSR(v0) 106 ctc1 v1, fcr31 107#endif /* __mips_hard_float */ 108 109 /* Note the contents of argument registers will be random 110 unless makecontext() has been called. */ 111 REG_L a0, (4 * SZREG + MCONTEXT_GREGS)(v0) 112 REG_L a1, (5 * SZREG + MCONTEXT_GREGS)(v0) 113 REG_L a2, (6 * SZREG + MCONTEXT_GREGS)(v0) 114 REG_L a3, (7 * SZREG + MCONTEXT_GREGS)(v0) 115#if _MIPS_SIM != _ABIO32 116 REG_L a4, (8 * SZREG + MCONTEXT_GREGS)(v0) 117 REG_L a5, (9 * SZREG + MCONTEXT_GREGS)(v0) 118 REG_L a6, (10 * SZREG + MCONTEXT_GREGS)(v0) 119 REG_L a7, (11 * SZREG + MCONTEXT_GREGS)(v0) 120#endif 121 122 REG_L s0, (16 * SZREG + MCONTEXT_GREGS)(v0) 123 REG_L s1, (17 * SZREG + MCONTEXT_GREGS)(v0) 124 REG_L s2, (18 * SZREG + MCONTEXT_GREGS)(v0) 125 REG_L s3, (19 * SZREG + MCONTEXT_GREGS)(v0) 126 REG_L s4, (20 * SZREG + MCONTEXT_GREGS)(v0) 127 REG_L s5, (21 * SZREG + MCONTEXT_GREGS)(v0) 128 REG_L s6, (22 * SZREG + MCONTEXT_GREGS)(v0) 129 REG_L s7, (23 * SZREG + MCONTEXT_GREGS)(v0) 130#if ! defined (__PIC__) || _MIPS_SIM != _ABIO32 131 REG_L gp, (28 * SZREG + MCONTEXT_GREGS)(v0) 132#endif 133 REG_L sp, (29 * SZREG + MCONTEXT_GREGS)(v0) 134 REG_L fp, (30 * SZREG + MCONTEXT_GREGS)(v0) 135 REG_L ra, (31 * SZREG + MCONTEXT_GREGS)(v0) 136 REG_L t9, MCONTEXT_PC(v0) 137 138 move v0, zero 139 jr t9 140 14198: 142 /* This is a context obtained from a signal handler. 143 Perform a full restore by pushing the context 144 passed onto a simulated signal frame on the stack 145 and call the signal return syscall as if a signal 146 handler exited normally. */ 147 PTR_ADDIU sp, -((RT_SIGFRAME_SIZE + ALSZ) & ALMASK) 148 149 /* Only ucontext is referred to from rt_sigreturn, 150 copy it. */ 151 PTR_ADDIU t1, sp, RT_SIGFRAME_UCONTEXT 152 li t3, ((UCONTEXT_SIZE + SZREG - 1) / SZREG) - 1 1530: 154 REG_L t2, (a0) 155 PTR_ADDIU a0, SZREG 156 REG_S t2, (t1) 157 PTR_ADDIU t1, SZREG 158 .set noreorder 159 bgtz t3, 0b 160 addiu t3, -1 161 .set reorder 162 163/* rt_sigreturn () -- no arguments, sp points to struct rt_sigframe. */ 164 li v0, SYS_ify (rt_sigreturn) 165 syscall 166 167 /* Restore the stack and fall through to the error 168 path. Successful rt_sigreturn never returns to 169 its calling place. */ 170 PTR_ADDIU sp, ((RT_SIGFRAME_SIZE + ALSZ) & ALMASK) 17199: 172#ifdef __PIC__ 173 PTR_LA t9, JUMPTARGET (__syscall_error) 174 RESTORE_GP64 175 PTR_ADDIU sp, FRAMESZ 176 jr t9 177 178#else /* ! __PIC__ */ 179 180 j JUMPTARGET (__syscall_error) 181#endif /* ! __PIC__ */ 182PSEUDO_END (__setcontext) 183 184weak_alias (__setcontext, setcontext) 185