1/* Jump to a new 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 setcontext 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	mflr	r0
42	stwu	r1,-16(r1)
43	cfi_adjust_cfa_offset (16)
44	stw	r0,20(r1)
45	cfi_offset (lr, _FRAME_LR_SAVE)
46	stw	r31,12(r1)
47	cfi_offset(r31,-4)
48	lwz	r31,_UC_REGS_PTR(r3)
49
50	/* Restore the signal mask */
51	li	r5,0
52	addi	r4,r3,_UC_SIGMASK
53	li	r3,SIG_SETMASK
54	bl	__sigprocmask@local
55	cmpwi	r3,0
56	bne	3f	/* L(error_exit) */
57
58#ifdef PIC
59	mflr    r8
60# define got_label GENERATE_GOT_LABEL (__CONTEXT_FUNC_NAME)
61	SETUP_GOT_ACCESS(r7,got_label)
62	addis	r7,r7,_GLOBAL_OFFSET_TABLE_-got_label@ha
63	addi	r7,r7,_GLOBAL_OFFSET_TABLE_-got_label@l
64# ifdef SHARED
65	lwz     r7,_rtld_global_ro@got(r7)
66	mtlr    r8
67	lwz     r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r7)
68# else
69	lwz     r7,_dl_hwcap@got(r7)
70	mtlr    r8
71	lwz     r7,LOWORD(r7)
72# endif
73#else
74	lis	r7,(_dl_hwcap+LOWORD)@ha
75	lwz     r7,(_dl_hwcap+LOWORD)@l(r7)
76#endif
77
78#ifdef __CONTEXT_ENABLE_FPRS
79# ifdef __CONTEXT_ENABLE_VRS
80	andis.	r6,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
81	la	r10,(_UC_VREGS)(r31)
82	beq	2f	/* L(has_no_vec) */
83
84	lwz   r0,(32*16)(r10)
85	li    r9,(32*16)
86	cmpwi r0,0
87	mtspr VRSAVE,r0
88	beq	2f	/* L(has_no_vec) */
89
90	lvx   v19,r9,r10
91	la    r9,(16)(r10)
92
93	lvx   v0,0,r10
94	lvx   v1,0,r9
95	addi  r10,r10,32
96	addi  r9,r9,32
97
98	mtvscr  v19
99	lvx   v2,0,r10
100	lvx   v3,0,r9
101	addi  r10,r10,32
102	addi  r9,r9,32
103
104	lvx   v4,0,r10
105	lvx   v5,0,r9
106	addi  r10,r10,32
107	addi  r9,r9,32
108
109	lvx   v6,0,r10
110	lvx   v7,0,r9
111	addi  r10,r10,32
112	addi  r9,r9,32
113
114	lvx   v8,0,r10
115	lvx   v9,0,r9
116	addi  r10,r10,32
117	addi  r9,r9,32
118
119	lvx   v10,0,r10
120	lvx   v11,0,r9
121	addi  r10,r10,32
122	addi  r9,r9,32
123
124	lvx   v12,0,r10
125	lvx   v13,0,r9
126	addi  r10,r10,32
127	addi  r9,r9,32
128
129	lvx   v14,0,r10
130	lvx   v15,0,r9
131	addi  r10,r10,32
132	addi  r9,r9,32
133
134	lvx   v16,0,r10
135	lvx   v17,0,r9
136	addi  r10,r10,32
137	addi  r9,r9,32
138
139	lvx   v18,0,r10
140	lvx   v19,0,r9
141	addi  r10,r10,32
142	addi  r9,r9,32
143
144	lvx   v20,0,r10
145	lvx   v21,0,r9
146	addi  r10,r10,32
147	addi  r9,r9,32
148
149	lvx   v22,0,r10
150	lvx   v23,0,r9
151	addi  r10,r10,32
152	addi  r9,r9,32
153
154	lvx   v24,0,r10
155	lvx   v25,0,r9
156	addi  r10,r10,32
157	addi  r9,r9,32
158
159	lvx   v26,0,r10
160	lvx   v27,0,r9
161	addi  r10,r10,32
162	addi  r9,r9,32
163
164	lvx   v28,0,r10
165	lvx   v29,0,r9
166	addi  r10,r10,32
167	addi  r9,r9,32
168
169	lvx   v30,0,r10
170	lvx   v31,0,r9
171	addi  r10,r10,32
172	addi  r9,r9,32
173
174	lvx   v10,0,r10
175	lvx   v11,0,r9
176
1772: /* L(has_no_vec): */
178# endif /* __CONTEXT_ENABLE_VRS */
179	/* Restore the floating-point registers */
180	lfd	fp31,_UC_FREGS+(32*8)(r31)
181	lfd	fp0,_UC_FREGS+(0*8)(r31)
182# ifdef _ARCH_PWR6
183	/* Use the extended four-operand version of the mtfsf insn.  */
184	mtfsf	0xff,fp31,1,0
185# else
186	.machine push
187	.machine "power6"
188	/* Availability of DFP indicates a 64-bit FPSCR.  */
189	andi.	r6,r7,PPC_FEATURE_HAS_DFP
190	beq	7f
191	/* Use the extended four-operand version of the mtfsf insn.  */
192	mtfsf	0xff,fp31,1,0
193	b	8f
194	/* Continue to operate on the FPSCR as if it were 32-bits.  */
1957:	mtfsf	0xff,fp31
1968:	.machine pop
197# endif /* _ARCH_PWR6 */
198	lfd	fp1,_UC_FREGS+(1*8)(r31)
199	lfd	fp2,_UC_FREGS+(2*8)(r31)
200	lfd	fp3,_UC_FREGS+(3*8)(r31)
201	lfd	fp4,_UC_FREGS+(4*8)(r31)
202	lfd	fp5,_UC_FREGS+(5*8)(r31)
203	lfd	fp6,_UC_FREGS+(6*8)(r31)
204	lfd	fp7,_UC_FREGS+(7*8)(r31)
205	lfd	fp8,_UC_FREGS+(8*8)(r31)
206	lfd	fp9,_UC_FREGS+(9*8)(r31)
207	lfd	fp10,_UC_FREGS+(10*8)(r31)
208	lfd	fp11,_UC_FREGS+(11*8)(r31)
209	lfd	fp12,_UC_FREGS+(12*8)(r31)
210	lfd	fp13,_UC_FREGS+(13*8)(r31)
211	lfd	fp14,_UC_FREGS+(14*8)(r31)
212	lfd	fp15,_UC_FREGS+(15*8)(r31)
213	lfd	fp16,_UC_FREGS+(16*8)(r31)
214	lfd	fp17,_UC_FREGS+(17*8)(r31)
215	lfd	fp18,_UC_FREGS+(18*8)(r31)
216	lfd	fp19,_UC_FREGS+(19*8)(r31)
217	lfd	fp20,_UC_FREGS+(20*8)(r31)
218	lfd	fp21,_UC_FREGS+(21*8)(r31)
219	lfd	fp22,_UC_FREGS+(22*8)(r31)
220	lfd	fp23,_UC_FREGS+(23*8)(r31)
221	lfd	fp24,_UC_FREGS+(24*8)(r31)
222	lfd	fp25,_UC_FREGS+(25*8)(r31)
223	lfd	fp26,_UC_FREGS+(26*8)(r31)
224	lfd	fp27,_UC_FREGS+(27*8)(r31)
225	lfd	fp28,_UC_FREGS+(28*8)(r31)
226	lfd	fp29,_UC_FREGS+(29*8)(r31)
227	lfd	fp30,_UC_FREGS+(30*8)(r31)
228	lfd	fp31,_UC_FREGS+(31*8)(r31)
229#endif /* __CONTEXT_ENABLE_FPRS */
230
231	/* Restore LR and CCR, and set CTR to the NIP value */
232	lwz	r3,_UC_GREGS+(PT_LNK*4)(r31)
233	lwz	r4,_UC_GREGS+(PT_NIP*4)(r31)
234	lwz	r5,_UC_GREGS+(PT_CCR*4)(r31)
235	mtlr	r3
236	mtctr	r4
237	mtcr	r5
238
239	/* Restore the general registers */
240	lwz	r1,_UC_GREGS+(PT_R1*4)(r31)
241	lwz	r3,_UC_GREGS+(PT_R3*4)(r31)
242	lwz	r4,_UC_GREGS+(PT_R4*4)(r31)
243	lwz	r5,_UC_GREGS+(PT_R5*4)(r31)
244	lwz	r6,_UC_GREGS+(PT_R6*4)(r31)
245	lwz	r7,_UC_GREGS+(PT_R7*4)(r31)
246	lwz	r8,_UC_GREGS+(PT_R8*4)(r31)
247	lwz	r9,_UC_GREGS+(PT_R9*4)(r31)
248	lwz	r10,_UC_GREGS+(PT_R10*4)(r31)
249	lwz	r11,_UC_GREGS+(PT_R11*4)(r31)
250	lwz	r12,_UC_GREGS+(PT_R12*4)(r31)
251	lwz	r13,_UC_GREGS+(PT_R13*4)(r31)
252	lwz	r14,_UC_GREGS+(PT_R14*4)(r31)
253	lwz	r15,_UC_GREGS+(PT_R15*4)(r31)
254	lwz	r16,_UC_GREGS+(PT_R16*4)(r31)
255	lwz	r17,_UC_GREGS+(PT_R17*4)(r31)
256	lwz	r18,_UC_GREGS+(PT_R18*4)(r31)
257	lwz	r19,_UC_GREGS+(PT_R19*4)(r31)
258	lwz	r20,_UC_GREGS+(PT_R20*4)(r31)
259	lwz	r21,_UC_GREGS+(PT_R21*4)(r31)
260	lwz	r22,_UC_GREGS+(PT_R22*4)(r31)
261	lwz	r23,_UC_GREGS+(PT_R23*4)(r31)
262	lwz	r24,_UC_GREGS+(PT_R24*4)(r31)
263	lwz	r25,_UC_GREGS+(PT_R25*4)(r31)
264	lwz	r26,_UC_GREGS+(PT_R26*4)(r31)
265	lwz	r27,_UC_GREGS+(PT_R27*4)(r31)
266	lwz	r28,_UC_GREGS+(PT_R28*4)(r31)
267	lwz	r29,_UC_GREGS+(PT_R29*4)(r31)
268	lwz	r30,_UC_GREGS+(PT_R30*4)(r31)
269	lwz	r31,_UC_GREGS+(PT_R31*4)(r31)
270
271	bctr
272
2733: /* L(error_exit): */
274	lwz	r31,12(r1)
275	lwz	r0,20(r1)
276	addi	r1,r1,16
277	mtlr	r0
278	blr
279
280END (__CONTEXT_FUNC_NAME)
281