summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/kvx/getcontext.S
diff options
context:
space:
mode:
Diffstat (limited to 'libc/sysdeps/linux/kvx/getcontext.S')
-rw-r--r--libc/sysdeps/linux/kvx/getcontext.S81
1 files changed, 81 insertions, 0 deletions
diff --git a/libc/sysdeps/linux/kvx/getcontext.S b/libc/sysdeps/linux/kvx/getcontext.S
new file mode 100644
index 000000000..9440f67ce
--- /dev/null
+++ b/libc/sysdeps/linux/kvx/getcontext.S
@@ -0,0 +1,81 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive for
+ * more details.
+ *
+ * Copyright (C) 2025 Kalray Inc.
+ * Author(s): Julian Vetter <jvetter@kalrayinc.com>
+ */
+
+#include <sysdep.h>
+
+#include "ucontext_i.h"
+
+ .text
+
+/*
+ * int getcontext (ucontext_t *ucp)
+ */
+ENTRY(__getcontext)
+ /* Save callee saved registers ($r14, $r18 - $r31)
+ * and some special registers */
+
+ /* Save the entire occtuple, although we only need $sp and $r14 */
+ so MCONTEXT_Q12[$r0] = $r12r13r14r15
+ get $r4 = $lc
+ ;;
+ /* Don't need to save veneer registers $r16 and $r17 */
+ sq (MCONTEXT_Q16 + 16)[$r0] = $r18r19
+ get $r5 = $le
+ ;;
+ so MCONTEXT_Q20[$r0] = $r20r21r22r23
+ get $r6 = $ls
+ ;;
+ so MCONTEXT_Q24[$r0] = $r24r25r26r27
+ get $r7 = $ra
+ ;;
+ so MCONTEXT_Q28[$r0] = $r28r29r30r31
+ get $r8 = $cs
+ ;;
+ so MCONTEXT_LC_LE_LS_RA[$r0] = $r4r5r6r7
+ /* Save ucp and $ra in callee saved registers because below we need to
+ * do a call to sigprocmask and afterwards we need to restore $ra. */
+ copyd $r20 = $r0
+ copyd $r21 = $r7
+ ;;
+ sd MCONTEXT_CS_SPC[$r0] = $r8
+
+ /* Prepare call to sigprocmask */
+ make $r0 = SIG_BLOCK
+ make $r1 = 0
+ ;;
+ /* $r20 points to the ucontext */
+ addd $r2 = $r20, UCONTEXT_SIGMASK
+ /* Already set the return value for when this is called in the context
+ * of swapcontext. Because when this context returns it should look
+ * like as if swapcontext returned with 0. */
+ sd MCONTEXT_Q0[$r20] = $r1
+ ;;
+ /* sigprocmask(SIG_BLOCK, NULL, &(ucontext->uc_sigmask)) */
+ call sigprocmask
+ ;;
+ /* Restore $ra to point to the caller of this function. So,
+ * __getcontext will return with -1 (set by __syscall_error) and an
+ * appropriate errno */
+ set $ra = $r21
+ ;;
+ /* Check return value of sigprocmask */
+ cb.deqz $r0 ? 1f
+ ;;
+ goto __syscall_error
+ ;;
+1:
+ /* Restore used callee saved registers */
+ lq $r20r21 = MCONTEXT_Q20[$r20]
+ ;;
+ /* Set return value */
+ make $r0 = 0
+ ret
+ ;;
+END(__getcontext)
+weak_alias(__getcontext, getcontext)