1/* Save current context, powerpc32 common.
2   Copyright (C) 2005-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/* This is the common implementation of getcontext for powerpc32.
20   It not complete in itself should be included in to a framework that
21   defines:
22     __CONTEXT_FUNC_NAME
23   and if appropriate:
24     __CONTEXT_ENABLE_FPRS
25     __CONTEXT_ENABLE_VRS
26   Any architecture that implements the Vector unit is assumed to also
27   implement the floating unit.  */
28
29/* Stack frame offsets.  */
30#define _FRAME_BACKCHAIN	0
31#define _FRAME_LR_SAVE		4
32#define _FRAME_PARM_SAVE1	8
33#define _FRAME_PARM_SAVE2	12
34#define _FRAME_PARM_SAVE3	16
35#define _FRAME_PARM_SAVE4	20
36
37#ifdef __CONTEXT_ENABLE_VRS
38	.machine	"altivec"
39#endif
40ENTRY(__CONTEXT_FUNC_NAME)
41	stwu	r1,-16(r1)
42	cfi_adjust_cfa_offset (16)
43/* Insure that the _UC_REGS start on a quadword boundary.  */
44	stw	r3,_FRAME_PARM_SAVE1(r1)
45	addi	r3,r3,_UC_REG_SPACE+12
46	clrrwi  r3,r3,4
47
48/* Save the general purpose registers */
49	stw	r0,_UC_GREGS+(PT_R0*4)(r3)
50	mflr	r0
51	stw	r2,_UC_GREGS+(PT_R2*4)(r3)
52	stw	r4,_UC_GREGS+(PT_R4*4)(r3)
53/* Set the callers LR_SAVE, and the ucontext LR and NIP to the callers
54   return address.  */
55	stw	r0,_UC_GREGS+(PT_LNK*4)(r3)
56	stw	r0,_UC_GREGS+(PT_NIP*4)(r3)
57	stw	r0,_FRAME_LR_SAVE+16(r1)
58	cfi_offset (lr, _FRAME_LR_SAVE)
59	stw	r5,_UC_GREGS+(PT_R5*4)(r3)
60	stw	r6,_UC_GREGS+(PT_R6*4)(r3)
61	stw	r7,_UC_GREGS+(PT_R7*4)(r3)
62	stw	r8,_UC_GREGS+(PT_R8*4)(r3)
63	stw	r9,_UC_GREGS+(PT_R9*4)(r3)
64	stw	r10,_UC_GREGS+(PT_R10*4)(r3)
65	stw	r11,_UC_GREGS+(PT_R11*4)(r3)
66	stw	r12,_UC_GREGS+(PT_R12*4)(r3)
67	stw	r13,_UC_GREGS+(PT_R13*4)(r3)
68	stw	r14,_UC_GREGS+(PT_R14*4)(r3)
69	stw	r15,_UC_GREGS+(PT_R15*4)(r3)
70	stw	r16,_UC_GREGS+(PT_R16*4)(r3)
71	stw	r17,_UC_GREGS+(PT_R17*4)(r3)
72	stw	r18,_UC_GREGS+(PT_R18*4)(r3)
73	stw	r19,_UC_GREGS+(PT_R19*4)(r3)
74	stw	r20,_UC_GREGS+(PT_R20*4)(r3)
75	stw	r21,_UC_GREGS+(PT_R21*4)(r3)
76	stw	r22,_UC_GREGS+(PT_R22*4)(r3)
77	stw	r23,_UC_GREGS+(PT_R23*4)(r3)
78	stw	r24,_UC_GREGS+(PT_R24*4)(r3)
79	stw	r25,_UC_GREGS+(PT_R25*4)(r3)
80	stw	r26,_UC_GREGS+(PT_R26*4)(r3)
81	stw	r27,_UC_GREGS+(PT_R27*4)(r3)
82	stw	r28,_UC_GREGS+(PT_R28*4)(r3)
83	stw	r29,_UC_GREGS+(PT_R29*4)(r3)
84	stw	r30,_UC_GREGS+(PT_R30*4)(r3)
85	stw	r31,_UC_GREGS+(PT_R31*4)(r3)
86/* Save the value of R1.  We had to push the stack before we
87   had the address of uc_reg_space.  So compute the address of
88   the callers stack pointer and save it as R1.  */
89	addi	r8,r1,16
90	li	r0,0
91/* Save the count, exception and condition registers.  */
92	mfctr	r11
93	mfxer	r10
94	mfcr	r9
95	stw	r8,_UC_GREGS+(PT_R1*4)(r3)
96	stw	r11,_UC_GREGS+(PT_CTR*4)(r3)
97	stw	r10,_UC_GREGS+(PT_XER*4)(r3)
98	stw	r9,_UC_GREGS+(PT_CCR*4)(r3)
99/* Set the return value of getcontext to "success".  R3 is the only
100   register whose value is not preserved in the saved context.  */
101	stw	r0,_UC_GREGS+(PT_R3*4)(r3)
102
103/* Zero fill fields that can't be set in user state. */
104	stw	r0,_UC_GREGS+(PT_MSR*4)(r3)
105	stw	r0,_UC_GREGS+(PT_MQ*4)(r3)
106
107#ifdef __CONTEXT_ENABLE_FPRS
108/* Save the floating-point registers */
109	stfd	fp0,_UC_FREGS+(0*8)(r3)
110	stfd	fp1,_UC_FREGS+(1*8)(r3)
111	stfd	fp2,_UC_FREGS+(2*8)(r3)
112	stfd	fp3,_UC_FREGS+(3*8)(r3)
113	stfd	fp4,_UC_FREGS+(4*8)(r3)
114	stfd	fp5,_UC_FREGS+(5*8)(r3)
115	stfd	fp6,_UC_FREGS+(6*8)(r3)
116	stfd	fp7,_UC_FREGS+(7*8)(r3)
117	stfd	fp8,_UC_FREGS+(8*8)(r3)
118	stfd	fp9,_UC_FREGS+(9*8)(r3)
119	stfd	fp10,_UC_FREGS+(10*8)(r3)
120	stfd	fp11,_UC_FREGS+(11*8)(r3)
121	stfd	fp12,_UC_FREGS+(12*8)(r3)
122	stfd	fp13,_UC_FREGS+(13*8)(r3)
123	stfd	fp14,_UC_FREGS+(14*8)(r3)
124	stfd	fp15,_UC_FREGS+(15*8)(r3)
125	stfd	fp16,_UC_FREGS+(16*8)(r3)
126	stfd	fp17,_UC_FREGS+(17*8)(r3)
127	stfd	fp18,_UC_FREGS+(18*8)(r3)
128	stfd	fp19,_UC_FREGS+(19*8)(r3)
129	stfd	fp20,_UC_FREGS+(20*8)(r3)
130	stfd	fp21,_UC_FREGS+(21*8)(r3)
131	stfd	fp22,_UC_FREGS+(22*8)(r3)
132	stfd	fp23,_UC_FREGS+(23*8)(r3)
133	stfd	fp24,_UC_FREGS+(24*8)(r3)
134	stfd	fp25,_UC_FREGS+(25*8)(r3)
135	stfd	fp26,_UC_FREGS+(26*8)(r3)
136	stfd	fp27,_UC_FREGS+(27*8)(r3)
137	stfd	fp28,_UC_FREGS+(28*8)(r3)
138	stfd	fp29,_UC_FREGS+(29*8)(r3)
139	mffs	fp0
140	stfd	fp30,_UC_FREGS+(30*8)(r3)
141	stfd	fp31,_UC_FREGS+(31*8)(r3)
142	stfd	fp0,_UC_FREGS+(32*8)(r3)
143
144# ifdef __CONTEXT_ENABLE_VRS
145#  ifdef PIC
146	mflr    r8
147#  define got_label GENERATE_GOT_LABEL (__CONTEXT_FUNC_NAME)
148	SETUP_GOT_ACCESS(r7,got_label)
149	addis	r7,r7,_GLOBAL_OFFSET_TABLE_-got_label@ha
150	addi	r7,r7,_GLOBAL_OFFSET_TABLE_-got_label@l
151#   ifdef SHARED
152	lwz     r7,_rtld_global_ro@got(r7)
153	mtlr    r8
154	lwz     r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r7)
155#   else
156	lwz     r7,_dl_hwcap@got(r7)
157	mtlr    r8
158	lwz     r7,LOWORD(r7)
159#   endif
160#  else
161	lis	r7,(_dl_hwcap+LOWORD)@ha
162	lwz     r7,(_dl_hwcap+LOWORD)@l(r7)
163#  endif
164	andis.	r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
165
166	la	r10,(_UC_VREGS)(r3)
167	la	r9,(_UC_VREGS+16)(r3)
168
169	beq	2f	/* L(no_vec) */
170/* address of the combined VSCR/VSAVE quadword.  */
171	la	r8,(_UC_VREGS+512)(r3)
172
173/* Save the vector registers */
174	stvx  v0,0,r10
175	stvx  v1,0,r9
176	addi  r10,r10,32
177	addi  r9,r9,32
178/* We need to get the Vector Status and Control Register early to avoid
179   store order problems later with the VSAVE register that shares the
180   same quadword.  */
181	mfvscr	v0
182
183	stvx  v2,0,r10
184	stvx  v3,0,r9
185	addi  r10,r10,32
186	addi  r9,r9,32
187
188	stvx	v0,0,r8
189
190	stvx  v4,0,r10
191	stvx  v5,0,r9
192	addi  r10,r10,32
193	addi  r9,r9,32
194
195	stvx  v6,0,r10
196	stvx  v7,0,r9
197	addi  r10,r10,32
198	addi  r9,r9,32
199
200	stvx  v8,0,r10
201	stvx  v9,0,r9
202	addi  r10,r10,32
203	addi  r9,r9,32
204
205	stvx  v10,0,r10
206	stvx  v11,0,r9
207	addi  r10,r10,32
208	addi  r9,r9,32
209
210	stvx  v12,0,r10
211	stvx  v13,0,r9
212	addi  r10,r10,32
213	addi  r9,r9,32
214
215	stvx  v14,0,r10
216	stvx  v15,0,r9
217	addi  r10,r10,32
218	addi  r9,r9,32
219
220	stvx  v16,0,r10
221	stvx  v17,0,r9
222	addi  r10,r10,32
223	addi  r9,r9,32
224
225	stvx  v18,0,r10
226	stvx  v19,0,r9
227	addi  r10,r10,32
228	addi  r9,r9,32
229
230	stvx  v20,0,r10
231	stvx  v21,0,r9
232	addi  r10,r10,32
233	addi  r9,r9,32
234
235	stvx  v22,0,r10
236	stvx  v23,0,r9
237	addi  r10,r10,32
238	addi  r9,r9,32
239
240	stvx  v24,0,r10
241	stvx  v25,0,r9
242	addi  r10,r10,32
243	addi  r9,r9,32
244
245	stvx  v26,0,r10
246	stvx  v27,0,r9
247	addi  r10,r10,32
248	addi  r9,r9,32
249
250	stvx  v28,0,r10
251	stvx  v29,0,r9
252	addi  r10,r10,32
253	addi  r9,r9,32
254
255	mfspr	r0,VRSAVE
256	stvx  v30,0,r10
257	stvx  v31,0,r9
258
259 	stw	r0,0(r8)
260
2612: /* L(no_vec): */
262# endif
263#endif
264
265/* We need to set up parms and call sigprocmask which will clobber
266   volatile registers. So before the call we need to retrieve the
267   original ucontext ptr (parm1) from stack and store the UC_REGS_PTR
268   (current R3).  */
269	lwz	r12,_FRAME_PARM_SAVE1(r1)
270	li	r4,0
271	stw	r3,_UC_REGS_PTR(r12)
272	addi	r5,r12,_UC_SIGMASK
273	li	r3,SIG_BLOCK
274	bl	__sigprocmask@local
275
276	lwz	r0,_FRAME_LR_SAVE+16(r1)
277	addi	r1,r1,16
278	mtlr	r0
279	blr
280END(__CONTEXT_FUNC_NAME)
281