| /* Modify saved context. |
| Copyright (C) 2009-2014 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 |
| .set nomips16 |
| 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 |
| cfi_adjust_cfa_offset (FRAMESZ) |
| |
| #ifdef __PIC__ |
| SETUP_GP64_STACK (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_STACK |
| PTR_ADDIU sp, FRAMESZ |
| cfi_adjust_cfa_offset (-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) |