/* Modify saved context. Copyright (C) 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Maciej W. Rozycki <macro@codesourcery.com>. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library. If not, see <http://www.gnu.org/licenses/>. */ #include <sysdep.h> #include <sys/asm.h> #include <sys/fpregdef.h> #include <sys/regdef.h> #include "ucontext_i.h" /* int makecontext (ucontext_t *ucp, (void *func) (), int argc, ...) */ .text LOCALSZ = 0 ARGSZ = 0 MASK = 0x00000000 #ifdef __PIC__ LOCALSZ = 1 /* save gp */ #endif #if _MIPS_SIM != _ABIO32 ARGSZ = 5 /* save a3-a7 */ # ifdef __PIC__ MASK = 0x10000000 # endif #endif FRAMESZ = (((ARGSZ + LOCALSZ) * SZREG) + ALSZ) & ALMASK GPOFF = FRAMESZ - ((ARGSZ + 1) * SZREG) #if _MIPS_SIM != _ABIO32 A3OFF = FRAMESZ - (5 * SZREG) /* callee-allocated */ A4OFF = FRAMESZ - (4 * SZREG) A5OFF = FRAMESZ - (3 * SZREG) A6OFF = FRAMESZ - (2 * SZREG) A7OFF = FRAMESZ - (1 * SZREG) NARGREGS = 8 #else A3OFF = FRAMESZ + (3 * SZREG) /* caller-allocated */ NARGREGS = 4 #endif NESTED (__makecontext, FRAMESZ, ra) .mask MASK, -(ARGSZ * SZREG) .fmask 0x00000000, 0 98: #ifdef __PIC__ SETUP_GP #endif PTR_ADDIU sp, -FRAMESZ #ifdef __PIC__ SETUP_GP64 (GPOFF, __makecontext) SAVE_GP (GPOFF) #endif #ifdef PROF .set noat move AT, ra jal _mcount .set at #endif /* Store args to be passed. */ REG_S a3, A3OFF(sp) #if _MIPS_SIM != _ABIO32 REG_S a4, A4OFF(sp) REG_S a5, A5OFF(sp) REG_S a6, A6OFF(sp) REG_S a7, A7OFF(sp) #endif /* Store a magic flag. */ li v1, 1 REG_S v1, (0 * SZREG + MCONTEXT_GREGS)(a0) /* zero */ /* Set up the stack. */ PTR_L t0, STACK_SP(a0) PTR_L t2, STACK_SIZE(a0) PTR_ADDIU t1, sp, A3OFF PTR_ADDU t0, t2 and t0, ALMASK blez a2, 2f /* no arguments */ /* Store register arguments. */ PTR_ADDIU t2, a0, MCONTEXT_GREGS + 4 * SZREG move t3, zero 0: addiu t3, 1 REG_L v1, (t1) PTR_ADDIU t1, SZREG REG_S v1, (t2) PTR_ADDIU t2, SZREG bgeu t3, a2, 2f /* all done */ bltu t3, NARGREGS, 0b /* next */ /* Make room for stack arguments. */ PTR_SUBU t2, a2, t3 PTR_SLL t2, 3 PTR_SUBU t0, t2 and t0, ALMASK /* Store stack arguments. */ move t2, t0 1: addiu t3, 1 REG_L v1, (t1) PTR_ADDIU t1, SZREG REG_S v1, (t2) PTR_ADDIU t2, SZREG bltu t3, a2, 1b /* next */ 2: #if _MIPS_SIM == _ABIO32 /* Make room for a0-a3 storage. */ PTR_ADDIU t0, -(NARGSAVE * SZREG) #endif PTR_L v1, UCONTEXT_LINK(a0) #ifdef __PIC__ PTR_ADDIU t9, 99f - 98b #else PTR_LA t9, 99f #endif REG_S t0, (29 * SZREG + MCONTEXT_GREGS)(a0) /* sp */ REG_S v1, (16 * SZREG + MCONTEXT_GREGS)(a0) /* s0 */ #ifdef __PIC__ REG_S gp, (17 * SZREG + MCONTEXT_GREGS)(a0) /* s1 */ #endif REG_S t9, (31 * SZREG + MCONTEXT_GREGS)(a0) /* ra */ REG_S a1, MCONTEXT_PC(a0) #ifdef __PIC__ RESTORE_GP64 PTR_ADDIU sp, FRAMESZ #endif jr ra 99: #ifdef __PIC__ move gp, s1 #endif move a0, zero beqz s0, 0f /* setcontext (ucp) */ move a0, s0 #ifdef __PIC__ PTR_LA t9, JUMPTARGET (__setcontext) jalr t9 # if _MIPS_SIM == _ABIO32 move gp, s1 # endif #else jal JUMPTARGET (__setcontext) #endif move a0, v0 0: /* exit (a0) */ #ifdef __PIC__ PTR_LA t9, HIDDEN_JUMPTARGET (exit) jalr t9 #else jal HIDDEN_JUMPTARGET (exit) #endif /* You don't exist, you won't feel anything. */ 1: lb zero, (zero) b 1b PSEUDO_END (__makecontext) weak_alias (__makecontext, makecontext)