1/* Install given context.
2   Copyright (C) 2008-2022 Free Software Foundation, Inc.
3   This file is part of the GNU C Library.
4
5   The GNU C Library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9
10   The GNU C Library is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
13   Lesser General Public License for more details.
14
15   You should have received a copy of the GNU Lesser General Public
16   License along with the GNU C Library.  If not, see
17   <https://www.gnu.org/licenses/>.  */
18
19#include <sysdep.h>
20#include <libc-symbols.h>
21
22#include "ucontext_i.h"
23
24
25ENTRY(__setcontext)
26	/* Prologue */
27	stw	%r2, -20(%sp)
28	.cfi_offset 2, -20
29	stwm	%r3, 64(%sp)
30	.cfi_def_cfa_offset -64
31	.cfi_offset 3, 0
32#ifdef PIC
33	stw	%r19, -32(%sp)
34	.cfi_offset 19, 32
35#endif
36	stw	%ret1, -60(%sp)
37	.cfi_offset 29, 4
38
39	/* Save ucp.  */
40	copy	%r26, %r3
41
42.Lagain:
43	/* Set the current signal mask.  */
44	/* sigprocmask(SIG_BLOCK, &ucp->uc_sigmask, NULL);  */
45	copy	%r0, %r24
46	ldo	oSIGMASK(%r3), %r25
47	bl	__sigprocmask, %r2
48	ldi	SIG_SETMASK, %r26
49
50	comib,<>,n 0,%ret0,.Lerror
51
52	/* Save %sp, %dp.  */
53	copy	%sp, %r4
54	copy	%dp, %r5
55	copy	%r19, %r6
56
57	/* Get the registers.  */
58	ldw	oR1(%r3), %r1
59	ldw	oR2(%r3), %r2
60	/* ldw	oR3(%r3), %r3 - used for ucp pointer.	*/
61	/* ldw	oR4(%r3), %r4 - used for original %sp.	*/
62	/* ldw	oR5(%r3), %r5 - used for %dp / %r27.	*/
63	/* ldw	oR6(%r3), %r6 - used for %r19.		*/
64	ldw	oR7(%r3), %r7
65	ldw	oR8(%r3), %r8
66	ldw	oR9(%r3), %r9
67	ldw	oR10(%r3), %r10
68	ldw	oR11(%r3), %r11
69	ldw	oR12(%r3), %r12
70	ldw	oR13(%r3), %r13
71	ldw	oR14(%r3), %r14
72	ldw	oR15(%r3), %r15
73	ldw	oR16(%r3), %r16
74	ldw	oR17(%r3), %r17
75	ldw	oR18(%r3), %r18
76	ldw	oR19(%r3), %r19
77	ldw	oR20(%r3), %r20
78	ldw	oR21(%r3), %r21 /* maybe clobbered by dyncall */
79	/* ldw	oR22(%r3), %r22 - dyncall arg.  */
80	ldw	oR23(%r3), %r23
81	ldw	oR24(%r3), %r24
82	ldw	oR25(%r3), %r25
83	ldw	oR26(%r3), %r26
84	ldw	oR27(%r3), %r27
85	ldw	oR28(%r3), %r28
86	ldw	oR29(%r3), %r29
87	ldw	oR30(%r3), %sp
88	/* ldw	oR31(%r3), %r31 - dyncall scratch register */
89
90	/* Restore SAR register.  */
91	ldw	oSAR(%r3), %r22
92	mtsar	%r22
93
94	/* Restore floating-point registers.  */
95	ldo	 oFPREGS31(%r3), %r22
96	fldds	  0(%r22), %fr31
97	fldds,mb -8(%r22), %fr30
98	fldds,mb -8(%r22), %fr29
99	fldds,mb -8(%r22), %fr28
100	fldds,mb -8(%r22), %fr27
101	fldds,mb -8(%r22), %fr26
102	fldds,mb -8(%r22), %fr25
103	fldds,mb -8(%r22), %fr24
104	fldds,mb -8(%r22), %fr23
105	fldds,mb -8(%r22), %fr22
106	fldds,mb -8(%r22), %fr21
107	fldds,mb -8(%r22), %fr20
108	fldds,mb -8(%r22), %fr19
109	fldds,mb -8(%r22), %fr18
110	fldds,mb -8(%r22), %fr17
111	fldds,mb -8(%r22), %fr16
112	fldds,mb -8(%r22), %fr15
113	fldds,mb -8(%r22), %fr14
114	fldds,mb -8(%r22), %fr13
115	fldds,mb -8(%r22), %fr12
116	fldds,mb -8(%r22), %fr11
117	fldds,mb -8(%r22), %fr10
118	fldds,mb -8(%r22), %fr9
119	fldds,mb -8(%r22), %fr8
120	fldds,mb -8(%r22), %fr7
121	fldds,mb -8(%r22), %fr6
122	fldds,mb -8(%r22), %fr5
123	fldds,mb -8(%r22), %fr4
124	fldds,mb -8(%r22), %fr3
125	fldds,mb -8(%r22), %fr2
126	fldds,mb -8(%r22), %fr1
127	fldds,mb -8(%r22), %fr0
128
129	/* Do not load oSS_SP into %sp. The value of oSS_SP indicates
130	   the start of the user allocated stack, but not the sp that
131	   should be used by the new context. In fact makecontext
132	   will create a frame, and adjust sp as required. We do not
133	   support calling getcontext and modifying ss_sp without
134	   a call to makecontext to synchronize ss_sp into the machine
135	   context.  */
136
137	/* Call external function.  */
138	copy	%r2, %r22
139	bl	$$dyncall, %r31
140	copy	%r31, %r2
141
142	/* We return here. Get new ucp in %r3, reload %sp.  */
143	ldw	oUC_LINK(%r3), %r3
144	copy	%r4, %sp
145	copy	%r5, %dp
146	copy	%r6, %r19
147
148	/* Continue until ucp == NULL.  */
149	comib,<> 0,%r3,.Lagain
150	nop
151
152	/* No further context available. Exit now.  */
153	bl	HIDDEN_JUMPTARGET(exit), %r2
154	ldi	0, %r26
155
156
157.Lerror:
158	/* Epilogue */
159	ldw	-84(%r30), %r2
160#ifdef PIC
161	ldw	-32(%r30), %r19
162#endif
163	ldw	-60(%r30), %ret1
164	bv	%r0(%r2)
165	ldwm	-64(%r30), %r3
166L(pseudo_end):
167PSEUDO_END(__setcontext)
168
169weak_alias(__setcontext, setcontext)
170