summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/nds32/getcontext.S
diff options
context:
space:
mode:
Diffstat (limited to 'libc/sysdeps/linux/nds32/getcontext.S')
-rw-r--r--libc/sysdeps/linux/nds32/getcontext.S106
1 files changed, 106 insertions, 0 deletions
diff --git a/libc/sysdeps/linux/nds32/getcontext.S b/libc/sysdeps/linux/nds32/getcontext.S
new file mode 100644
index 000000000..7bc1ca292
--- /dev/null
+++ b/libc/sysdeps/linux/nds32/getcontext.S
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Copyright (C) 20[B01-2013 Free Software Foundation, Inc.
+ Contributed by Martin Schwidefsky (schwidefsky@de.ibm.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 "ucontext_i.h"
+
+/* __getcontext (const ucontext_t *ucp)
+
+ Saves the machine context in UCP such that when it is activated,
+ it appears as if __getcontext() returned again.
+
+ This implementation is intended to be used for *synchronous* context
+ switches only. Therefore, it does not have to save anything
+ other than the PRESERVED state. */
+
+ENTRY(__getcontext)
+ swi $lp, [$r0 + UCONTEXT_PC]
+ addi $r15, $r0, UCONTEXT_GREGS
+ xor $r1, $r1, $r1
+ smw.bim $r1, [$r15], $r1
+ smw.bim $r1, [$r15], $r14
+ addi $r15, $r15, 4
+ smw.bim $r16, [$r15], $r25, #0xf
+ move $r4, $r0
+
+ /* sigprocmask (SIG_BLOCK, NULL, &sc->sc_mask). */
+ move $r0, SIG_BLOCK
+ move $r1, 0
+ addi $r2, $r4, UCONTEXT_SIGMASK
+ move $r3, _NSIG8
+ syscall SYS_ify(rt_sigprocmask)
+ bnez $r0, 1f
+
+
+#ifdef __NDS32_ABI_2FP_PLUS__
+ addi $r2, $r4, UCONTEXT_FDREGS
+/* Process for FPU registers. */
+ fmfcfg $r20 /* Keep $fpcfg in $r20. */
+ slli $r20, $r20, #28
+ srli $r20, $r20, #30 /* Set $r20 as $fpcfg.freg. */
+
+ /* Case switch for $r20 as $fpcfg.freg. */
+ beqz $r20, .LCFG0 /* Branch if $fpcfg.freg = 0b00. */
+ xori $r15, $r20, #0b10
+ beqz $r15, .LCFG2 /* Branch if $fpcfg.freg = 0b10. */
+ srli $r20, $r20, #0b01
+ beqz $r20, .LCFG1 /* Branch if $fpcfg.freg = 0b01. */
+ /* Fall-through if $fpcfg.freg = 0b11. */
+.LCFG3:
+ fsdi $fd31, [$r2 + 248]
+ fsdi $fd30, [$r2 + 240]
+ fsdi $fd29, [$r2 + 232]
+ fsdi $fd28, [$r2 + 224]
+ fsdi $fd27, [$r2 + 216]
+ fsdi $fd26, [$r2 + 208]
+ fsdi $fd25, [$r2 + 200]
+ fsdi $fd24, [$r2 + 192]
+.LCFG2:
+ fsdi $fd10, [$r2 + 80]
+ fsdi $fd9, [$r2 + 72]
+ fsdi $fd8, [$r2 + 64]
+.LCFG1:
+ fsdi $fd7, [$r2 + 56]
+ fsdi $fd6, [$r2 + 48]
+ fsdi $fd5, [$r2 + 40]
+ fsdi $fd4, [$r2 + 32]
+.LCFG0:
+ fsdi $fd3, [$r2 + 24]
+ /*save fpcsr*/
+ fmfcsr $r1
+ swi $r1, [$r2 + 0x100]
+#endif /* __NDS32_ABI_2FP_PLUS__ */
+
+ /* Set __getcontext return value to 0. */
+ xor $r0, $r0, $r0
+ /* Return first_return: 1 */
+ addi $r1, $r0, 1
+ ret
+
+1:
+ move $r0, -1
+ ret
+END(__getcontext)
+
+weak_alias (__getcontext, getcontext)
+