summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/kvx/setcontext.S
blob: 7b91d21d978bc9f90c671330cc0699c5746f2f7b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/*
 * 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 setcontext (const ucontext_t *ucp)
 */
ENTRY(__setcontext)
	get $r16 = $ra
	addd $r12 = $r12, -32
	;;
	/* Save ucp pointer  and $ra on the stack because we can't trash
	 * any callee saved registers in case __setcontext returns */
	sd 16[$r12] = $r16
	;;
	sd 24[$r12] = $r0
	;;
	/* Bring back the signal status. */
	make $r0 = SIG_SETMASK
	addd $r1 = $r0, UCONTEXT_SIGMASK
	make $r2 = 0
	;;
	/* sigprocmask(SIG_SETMASK, &(ucontext->uc_sigmask), NULL) */
	call sigprocmask
	;;
	/* Check return value of sigprocmask */
	cb.deqz $r0 ? 1f
	/* Normally __setcontext does not return. But in case of an error it
	 * returns with -1 and an appropriate errno */
	ld $r16 = 16[$r12]
	;;
	set $ra = $r16
	addd $r12 = $r12, 32
	;;
	goto __syscall_error
	;;
1:
	/* Get back the ucp pointer */
	ld $r16 = 24[$r12]
	/* Reset the stack pointer (we can trash $ra here, because we will
	 * never return to after __setcontext from this point onwards) */
	addd $r12 = $r12, 32
	;;
	/* Restore callee saved registers */
	lq $r18r19 = (MCONTEXT_Q16 + 16)[$r16]
	;;
	/* Setup $r20, $r21 for the __startcontext to work */
	lo $r20r21r22r23 = MCONTEXT_Q20[$r16]
	;;
	lo $r24r25r26r27 = MCONTEXT_Q24[$r16]
	;;
	lo $r28r29r30r31 = MCONTEXT_Q28[$r16]
	;;
	/* Restore special registers */
	lo $r40r41r42r43 = MCONTEXT_LC_LE_LS_RA[$r16]
	;;
	/* Now load argument registers */
	lo $r0r1r2r3 = MCONTEXT_Q0[$r16]
	set $lc = $r40
	;;
	lo $r4r5r6r7 = MCONTEXT_Q4[$r16]
	set $le = $r41
	;;
	lo $r8r9r10r11 = MCONTEXT_Q8[$r16]
	set $ls = $r42
	;;
	/* Restore $sp */
	ld $r12 = MCONTEXT_Q12[$r16]
	/* Restore $ra which points to the $ra set by __getcontext or
	 * to__startcontext if __makecontext was called in between */
	set $ra = $r43
	;;
	ld $r40 = MCONTEXT_CS_SPC[$r16]
	;;
	ld $r14 = (MCONTEXT_Q12 + 16)[$r16]
	set $cs = $r40
	;;
	ret
	;;
END(setcontext)
weak_alias(__setcontext, setcontext)

ENTRY(__startcontext)
	icall $r21
	;;
	copyd $r0 = $r20
	/* Check if the new context is 0 if so just call _exit */
	cb.deqz $r20 ? 1f
	;;
	goto __setcontext
	;;
	/* This should never be reached otherwise kill the thread */
1:	goto _exit
	;;
END(__startcontext)