diff options
Diffstat (limited to 'sysdeps/unix/sysv/linux/aarch64/getcontext.S')
-rw-r--r-- | sysdeps/unix/sysv/linux/aarch64/getcontext.S | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/linux/aarch64/getcontext.S b/sysdeps/unix/sysv/linux/aarch64/getcontext.S new file mode 100644 index 0000000000..70b2e32431 --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/getcontext.S @@ -0,0 +1,108 @@ +/* Save current context. + + Copyright (C) 2009-2014 Free Software Foundation, Inc. + + This file is part of the GNU C Library. + + 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 "ucontext_i.h" +#include "ucontext-internal.h" + +/* int getcontext (ucontext_t *ucp) + + Returns 0 on success -1 and errno on failure. + */ + + .text + +ENTRY(__getcontext) + /* The saved context will return to the getcontext() call point + with a return value of 0 */ + str xzr, [x0, oX0 + 0 * SZREG] + + stp x18, x19, [x0, oX0 + 18 * SZREG] + stp x20, x21, [x0, oX0 + 20 * SZREG] + stp x22, x23, [x0, oX0 + 22 * SZREG] + stp x24, x25, [x0, oX0 + 24 * SZREG] + stp x26, x27, [x0, oX0 + 26 * SZREG] + stp x28, x29, [x0, oX0 + 28 * SZREG] + str x30, [x0, oX0 + 30 * SZREG] + + /* Place LR into the saved PC, this will ensure that when + switching to this saved context with setcontext() control + will pass back to the caller of getcontext(), we have + already arrange to return the appropriate return value in x0 + above. */ + str x30, [x0, oPC] + + /* Save the current SP */ + mov x2, sp + str x2, [x0, oSP] + + /* Initialize the pstate. */ + str xzr, [x0, oPSTATE] + + /* Figure out where to place the first context extension + block. */ + add x2, x0, #oEXTENSION + + /* Write the context extension fpsimd header. */ + mov w3, #(FPSIMD_MAGIC & 0xffff) + movk w3, #(FPSIMD_MAGIC >> 16), lsl #16 + str w3, [x2, #oHEAD + oMAGIC] + mov w3, #FPSIMD_CONTEXT_SIZE + str w3, [x2, #oHEAD + oSIZE] + + /* Fill in the FP SIMD context. */ + add x3, x2, #oV0 + 8 * SZVREG + stp d8, d9, [x3], # 2 * SZVREG + stp d10, d11, [x3], # 2 * SZVREG + stp d12, d13, [x3], # 2 * SZVREG + stp d14, d15, [x3], # 2 * SZVREG + + add x3, x2, oFPSR + + mrs x4, fpsr + str w4, [x3] + + mrs x4, fpcr + str w4, [x3, oFPCR - oFPSR] + + /* Write the termination context extension header. */ + add x2, x2, #FPSIMD_CONTEXT_SIZE + + str xzr, [x2, #oHEAD + oMAGIC] + str xzr, [x2, #oHEAD + oSIZE] + + /* Grab the signal mask */ + /* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */ + add x2, x0, #UCONTEXT_SIGMASK + mov x0, SIG_BLOCK + mov x1, 0 + mov x3, _NSIG8 + mov x8, SYS_ify (rt_sigprocmask) + svc 0 + cbnz x0, 1f + + /* Return 0 for success */ + mov x0, 0 + RET +1: + b C_SYMBOL_NAME(__syscall_error) + + PSEUDO_END (__getcontext) +weak_alias (__getcontext, getcontext) |