| /* Copyright (C) 2011-2018 Free Software Foundation, Inc. |
| This file is part of the GNU C Library. |
| Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011. |
| |
| 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 <arch/abi.h> |
| |
| #include "ucontext_i.h" |
| |
| /* int getcontext (ucontext_t *ucp) */ |
| |
| .text |
| ENTRY (__getcontext) |
| FEEDBACK_ENTER(__getcontext) |
| |
| /* Save the callee-saved GPRs. There's no need to save the |
| caller-saved GPRs since the eventual setcontext() or |
| swapcontext() will assume those registers are all dead. |
| Save value "1" to uc_flags to later recognize getcontext(). */ |
| { movei r11, 1; ADDI_PTR r10, r0, UC_FLAGS_OFFSET } |
| { ST_PTR r10, r11; addli r10, r0, UC_REG(30) } |
| { st r10, r30; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, r31; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, r32; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, r33; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, r34; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, r35; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, r36; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, r37; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, r38; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, r39; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, r40; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, r41; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, r42; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, r43; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, r44; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, r45; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, r46; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, r47; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, r48; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, r49; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, r50; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, r51; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, r52; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, tp; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, sp; ADDI_PTR r10, r10, REGSIZE } |
| { st r10, lr; ADDI_PTR r10, r10, REGSIZE } |
| lnk r11 /* Point PC at the "jrp lr" instruction. */ |
| addli r11, r11, .Lreturn - . |
| { st r10, r11; ADDI_PTR r10, r10, REGSIZE } |
| mfspr r11, INTERRUPT_CRITICAL_SECTION |
| { |
| st r10, r11 |
| movei r1, 0 |
| } |
| |
| /* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG / 8) */ |
| { |
| movei r3, _NSIG / 8 |
| addli r2, r0, UC_SIGMASK_OFFSET |
| } |
| { |
| movei r0, SIG_BLOCK |
| moveli TREG_SYSCALL_NR_NAME, __NR_rt_sigprocmask |
| } |
| swint1 |
| bnez r1, .Lsyscall_error |
| |
| .Lreturn: |
| { |
| movei r0, 0 |
| jrp lr |
| } |
| |
| .Lsyscall_error: |
| j SYSCALL_ERROR_NAME |
| |
| END (__getcontext) |
| .hidden __getcontext |
| |
| weak_alias (__getcontext, getcontext) |