1/* Copyright (C) 2001-2022 Free Software Foundation, Inc.
2   This file is part of the GNU C Library.
3
4   The GNU C Library is free software; you can redistribute it and/or
5   modify it under the terms of the GNU Lesser General Public
6   License as published by the Free Software Foundation; either
7   version 2.1 of the License, or (at your option) any later version.
8
9   The GNU C Library is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   Lesser General Public License for more details.
13
14   You should have received a copy of the GNU Lesser General Public
15   License along with the GNU C Library; if not, see
16   <https://www.gnu.org/licenses/>.  */
17
18#include <sysdep.h>
19#include <features.h>
20
21#include "ucontext_i.h"
22
23/*  __setcontext (const ucontext_t *ucp)
24
25  Restores the machine context in UCP and thereby resumes execution
26  in that context.
27
28  This implementation in intended to be used for *synchronous* context
29  switches only.  Therefore, it does not have to restore anything
30  other than the PRESERVED state.  */
31
32ENTRY(__setcontext)
33	.prologue
34	.body
35	alloc r11 = ar.pfs, 1, 0, 4, 0
36
37	// sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL):
38
39	mov r3 = SC_MASK
40	mov out0 = SIG_SETMASK
41	;;
42	add out1 = r3, in0
43	mov out2 = 0
44	mov out3 = 8	// sizeof kernel sigset_t
45
46	invala
47	DO_CALL(__NR_rt_sigprocmask)
48	add r2 = SC_NAT, r32
49
50	add r3 = SC_RNAT, r32			// r3 <- &sc_ar_rnat
51	add rPOS = SC_GR, r32			// rPOS <- &sc_gr[0]
52	;;
53	ld8 rNAT = [r2], (SC_BSP-SC_NAT)
54	extr.u rPOS = rPOS, 3, 6		// get NaT bit number for r0
55	;;
56	ld8 rBSP = [r2], (SC_UNAT-SC_BSP)
57	ld8 rRNAT = [r3], (SC_FPSR-SC_RNAT)
58	/*
59	 * Rotate NaT bits by rPOS positions to the left:
60	 */
61	sub rCPOS = 64, rPOS
62	;;
63	ld8 rUNAT = [r2], (SC_PFS-SC_UNAT)
64	ld8 rFPSR = [r3], (SC_LC-SC_FPSR)
65	shl rTMP = rNAT, rPOS
66	;;
67	ld8 rPFS = [r2], (SC_PR-SC_PFS)
68	ld8 rLC = [r3], (SC_BR+0*8-SC_LC)
69	shr.u rNAT = rNAT, rCPOS
70	;;
71	ld8 rPR = [r2], (SC_BR+1*8-SC_PR)
72	ld8 rB0 = [r3], 16
73	or rNAT = rNAT, rTMP
74	;;
75	ld8 rB1 = [r2], 16
76	ld8 rB2 = [r3], 16
77	;;
78	mov.m ar.unat = rNAT
79	mov.m rRSC = ar.rsc
80	;;
81	ld8 rB3 = [r2], 16
82	ld8 rB4 = [r3], (SC_GR+1*8-(SC_BR+4*8))
83	;;
84	ld8 rB5 = [r2], (SC_GR+4*8-(SC_BR+5*8))
85	ld8.fill r1 = [r3], (5*8 - 1*8)
86	;;
87	ld8.fill r4 = [r2], 16
88	ld8.fill r5 = [r3], 16
89	mov b0 = rB0
90	;;
91	ld8.fill r6 = [r2], 48
92	ld8.fill r7 = [r3], (SC_FR+2*16-(SC_GR+7*8))
93	;;
94	ld8.fill sp = [r2], (SC_FR+3*16-(SC_GR+12*8))
95	mov.m ar.fpsr = rFPSR
96	mov.i ar.pfs = rPFS
97	;;
98	ldf.fill f3 = [r2], 16
99	ldf.fill f2 = [r3], 48
100	mov b1 = rB1
101	;;
102	ldf.fill f4 = [r2], (16*16-4*16)
103	ldf.fill f5 = [r3], (17*16-5*16)
104	mov b2 = rB2
105	;;
106	ldf.fill f16 = [r2], 32
107	ldf.fill f17 = [r3], 32
108	mov b3 = rB3
109	;;
110	ldf.fill f18 = [r2], 32
111	ldf.fill f19 = [r3], 32
112	mov b4 = rB4
113	;;
114	ldf.fill f20 = [r2], 32
115	ldf.fill f21 = [r3], 32
116	mov b5 = rB5
117	;;
118	ldf.fill f22 = [r2], 32
119	ldf.fill f23 = [r3], 32
120	mov r8 = 0
121	;;
122	ldf.fill f24 = [r2], 32
123	ldf.fill f25 = [r3], 32
124	mov r9 = 0
125	;;
126	ldf.fill f26 = [r2], 32
127	ldf.fill f27 = [r3], 32
128	dep rTMP = 0, rRSC, 16, 14	// clear ar.rsc.loadrs
129	;;
130	ldf.fill f28 = [r2], 32
131	ldf.fill f29 = [r3], 32
132	and rTMP = ~0x3, rTMP		// clear ar.rsc.mode
133	;;
134	ldf.fill f30 = [r2], 32
135	ldf.fill f31 = [r3], 32
136	mov pr = rPR, -1
137	;;
138	mov.m ar.rsc = rTMP		// put RSE into enforced lazy mode
139	;;
140	loadrs				// drop dirty partition
141	;;
142	mov.m ar.bspstore = rBSP
143	mov.m ar.unat = rUNAT
144	mov.i ar.lc = rLC
145	;;
146	mov.m ar.rnat = rRNAT
147	mov.m ar.rsc = rRSC
148	ret
149END(__setcontext)
150
151weak_alias (__setcontext, setcontext)
152