]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / powerpc / powerpc32 / swapcontext-common.S
CommitLineData
c50ce9a4 1/* Save current context and jump to a new context.
bfff8b1b 2 Copyright (C) 2005-2017 Free Software Foundation, Inc.
c50ce9a4
UD
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
59ba27a6
PE
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
c50ce9a4
UD
18
19/* This is the common implementation of setcontext for powerpc32.
b7219e53 20 It not complete in itself should be included in to a framework that
c50ce9a4
UD
21 defines:
22 __CONTEXT_FUNC_NAME
23 and if appropriate:
24 __CONTEXT_ENABLE_FPRS
25 __CONTEXT_ENABLE_VRS
6f65e668 26 Any architecture that implements the Vector unit is assumed to also
c50ce9a4
UD
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)
a7e91561 42 cfi_adjust_cfa_offset (16)
c50ce9a4
UD
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 stw r4,_FRAME_PARM_SAVE2(r1) /* new context pointer */
47 clrrwi r3,r3,4
48
49/* Save the general purpose registers */
50 stw r0,_UC_GREGS+(PT_R0*4)(r3)
51 mflr r0
52 stw r2,_UC_GREGS+(PT_R2*4)(r3)
b7219e53 53 stw r4,_UC_GREGS+(PT_R4*4)(r3)
c50ce9a4
UD
54/* Set the callers LR_SAVE, and the ucontext LR and NIP to the callers
55 return address. */
56 stw r0,_UC_GREGS+(PT_LNK*4)(r3)
57 stw r0,_UC_GREGS+(PT_NIP*4)(r3)
58 stw r0,_FRAME_LR_SAVE+16(r1)
a7e91561 59 cfi_offset (lr, _FRAME_LR_SAVE)
c50ce9a4
UD
60 stw r5,_UC_GREGS+(PT_R5*4)(r3)
61 stw r6,_UC_GREGS+(PT_R6*4)(r3)
62 stw r7,_UC_GREGS+(PT_R7*4)(r3)
63 stw r8,_UC_GREGS+(PT_R8*4)(r3)
64 stw r9,_UC_GREGS+(PT_R9*4)(r3)
65 stw r10,_UC_GREGS+(PT_R10*4)(r3)
66 stw r11,_UC_GREGS+(PT_R11*4)(r3)
67 stw r12,_UC_GREGS+(PT_R12*4)(r3)
68 stw r13,_UC_GREGS+(PT_R13*4)(r3)
69 stw r14,_UC_GREGS+(PT_R14*4)(r3)
70 stw r15,_UC_GREGS+(PT_R15*4)(r3)
71 stw r16,_UC_GREGS+(PT_R16*4)(r3)
72 stw r17,_UC_GREGS+(PT_R17*4)(r3)
73 stw r18,_UC_GREGS+(PT_R18*4)(r3)
74 stw r19,_UC_GREGS+(PT_R19*4)(r3)
75 stw r20,_UC_GREGS+(PT_R20*4)(r3)
76 stw r21,_UC_GREGS+(PT_R21*4)(r3)
77 stw r22,_UC_GREGS+(PT_R22*4)(r3)
78 stw r23,_UC_GREGS+(PT_R23*4)(r3)
79 stw r24,_UC_GREGS+(PT_R24*4)(r3)
80 stw r25,_UC_GREGS+(PT_R25*4)(r3)
81 stw r26,_UC_GREGS+(PT_R26*4)(r3)
82 stw r27,_UC_GREGS+(PT_R27*4)(r3)
83 stw r28,_UC_GREGS+(PT_R28*4)(r3)
84 stw r29,_UC_GREGS+(PT_R29*4)(r3)
85 stw r30,_UC_GREGS+(PT_R30*4)(r3)
86 stw r31,_UC_GREGS+(PT_R31*4)(r3)
b7219e53 87
c50ce9a4
UD
88/* Save the value of R1. We had to push the stack before we
89 had the address of uc_reg_space. So compute the address of
90 the callers stack pointer and save it as R1. */
91 addi r8,r1,16
92 li r0,0
93/* Save the count, exception and condition registers. */
94 mfctr r11
95 mfxer r10
96 mfcr r9
97 stw r8,_UC_GREGS+(PT_R1*4)(r3)
98 stw r11,_UC_GREGS+(PT_CTR*4)(r3)
99 stw r10,_UC_GREGS+(PT_XER*4)(r3)
100 stw r9,_UC_GREGS+(PT_CCR*4)(r3)
101/* Set the return value of getcontext to "success". R3 is the only
102 register whose value is not preserved in the saved context. */
103 stw r0,_UC_GREGS+(PT_R3*4)(r3)
104
105 /* Zero fill fields that can't be set in user state. */
106 stw r0,_UC_GREGS+(PT_MSR*4)(r3)
107 stw r0,_UC_GREGS+(PT_MQ*4)(r3)
108
109#ifdef __CONTEXT_ENABLE_FPRS
110 /* Save the floating-point registers */
111 stfd fp0,_UC_FREGS+(0*8)(r3)
112 stfd fp1,_UC_FREGS+(1*8)(r3)
113 stfd fp2,_UC_FREGS+(2*8)(r3)
114 stfd fp3,_UC_FREGS+(3*8)(r3)
115 stfd fp4,_UC_FREGS+(4*8)(r3)
116 stfd fp5,_UC_FREGS+(5*8)(r3)
117 stfd fp6,_UC_FREGS+(6*8)(r3)
118 stfd fp7,_UC_FREGS+(7*8)(r3)
119 stfd fp8,_UC_FREGS+(8*8)(r3)
120 stfd fp9,_UC_FREGS+(9*8)(r3)
121 stfd fp10,_UC_FREGS+(10*8)(r3)
122 stfd fp11,_UC_FREGS+(11*8)(r3)
123 stfd fp12,_UC_FREGS+(12*8)(r3)
124 stfd fp13,_UC_FREGS+(13*8)(r3)
125 stfd fp14,_UC_FREGS+(14*8)(r3)
126 stfd fp15,_UC_FREGS+(15*8)(r3)
127 stfd fp16,_UC_FREGS+(16*8)(r3)
128 stfd fp17,_UC_FREGS+(17*8)(r3)
129 stfd fp18,_UC_FREGS+(18*8)(r3)
130 stfd fp19,_UC_FREGS+(19*8)(r3)
131 stfd fp20,_UC_FREGS+(20*8)(r3)
132 stfd fp21,_UC_FREGS+(21*8)(r3)
133 stfd fp22,_UC_FREGS+(22*8)(r3)
134 stfd fp23,_UC_FREGS+(23*8)(r3)
135 stfd fp24,_UC_FREGS+(24*8)(r3)
136 stfd fp25,_UC_FREGS+(25*8)(r3)
137 stfd fp26,_UC_FREGS+(26*8)(r3)
138 stfd fp27,_UC_FREGS+(27*8)(r3)
139 stfd fp28,_UC_FREGS+(28*8)(r3)
140 stfd fp29,_UC_FREGS+(29*8)(r3)
141 mffs fp0
142 stfd fp30,_UC_FREGS+(30*8)(r3)
143 stfd fp31,_UC_FREGS+(31*8)(r3)
144 stfd fp0,_UC_FREGS+(32*8)(r3)
edba7a54
UD
145
146# ifdef PIC
c50ce9a4 147 mflr r8
929d11c7 148# define got_label GENERATE_GOT_LABEL (__CONTEXT_FUNC_NAME)
91d2a845
WS
149 SETUP_GOT_ACCESS(r7,got_label)
150 addis r7,r7,_GLOBAL_OFFSET_TABLE_-got_label@ha
151 addi r7,r7,_GLOBAL_OFFSET_TABLE_-got_label@l
edba7a54 152# ifdef SHARED
c50ce9a4
UD
153 lwz r7,_rtld_global_ro@got(r7)
154 mtlr r8
02f04a6c 155 lwz r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r7)
edba7a54 156# else
c50ce9a4
UD
157 lwz r7,_dl_hwcap@got(r7)
158 mtlr r8
02f04a6c 159 lwz r7,LOWORD(r7)
c50ce9a4 160# endif
edba7a54 161# else
02f04a6c
AM
162 lis r7,(_dl_hwcap+LOWORD)@ha
163 lwz r7,(_dl_hwcap+LOWORD)@l(r7)
edba7a54
UD
164# endif
165
166# ifdef __CONTEXT_ENABLE_VRS
167 andis. r6,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
c50ce9a4
UD
168
169 la r10,(_UC_VREGS)(r3)
170 la r9,(_UC_VREGS+16)(r3)
b7219e53 171
c50ce9a4
UD
172/* beq L(no_vec)*/
173 beq 2f
b7219e53 174/* address of the combined VSCR/VSAVE quadword. */
c50ce9a4
UD
175 la r8,(_UC_VREGS+512)(r3)
176
177/* Save the vector registers */
178 stvx v0,0,r10
179 stvx v1,0,r9
180 addi r10,r10,32
181 addi r9,r9,32
182/* We need to get the Vector Status and Control Register early to avoid
183 store order problems later with the VSAVE register that shares the
184 same quadword. */
185 mfvscr v0
186
187 stvx v2,0,r10
188 stvx v3,0,r9
189 addi r10,r10,32
190 addi r9,r9,32
b7219e53 191
c50ce9a4
UD
192 stvx v0,0,r8
193
194 stvx v4,0,r10
195 stvx v5,0,r9
196 addi r10,r10,32
197 addi r9,r9,32
198
199 stvx v6,0,r10
200 stvx v7,0,r9
201 addi r10,r10,32
202 addi r9,r9,32
203
204 stvx v8,0,r10
205 stvx v9,0,r9
206 addi r10,r10,32
207 addi r9,r9,32
208
209 stvx v10,0,r10
210 stvx v11,0,r9
211 addi r10,r10,32
212 addi r9,r9,32
213
214 stvx v12,0,r10
215 stvx v13,0,r9
216 addi r10,r10,32
217 addi r9,r9,32
218
219 stvx v14,0,r10
220 stvx v15,0,r9
221 addi r10,r10,32
222 addi r9,r9,32
223
224 stvx v16,0,r10
225 stvx v17,0,r9
226 addi r10,r10,32
227 addi r9,r9,32
228
229 stvx v18,0,r10
230 stvx v19,0,r9
231 addi r10,r10,32
232 addi r9,r9,32
233
234 stvx v20,0,r10
235 stvx v21,0,r9
236 addi r10,r10,32
237 addi r9,r9,32
238
239 stvx v22,0,r10
240 stvx v23,0,r9
241 addi r10,r10,32
242 addi r9,r9,32
243
244 stvx v24,0,r10
245 stvx v25,0,r9
246 addi r10,r10,32
247 addi r9,r9,32
248
249 stvx v26,0,r10
250 stvx v27,0,r9
251 addi r10,r10,32
252 addi r9,r9,32
253
254 stvx v28,0,r10
255 stvx v29,0,r9
256 addi r10,r10,32
257 addi r9,r9,32
258
259 mfvscr v0
260 stvx v30,0,r10
261 stvx v31,0,r9
262 stw r0,0(r8)
b7219e53 263
c50ce9a4
UD
2642: /*L(no_vec):*/
265# endif /* __CONTEXT_ENABLE_VRS */
266#endif /* __CONTEXT_ENABLE_FPRS */
267
cd78f7e7
JM
268#ifdef __CONTEXT_ENABLE_E500
269 getcontext_e500
270#endif
271
c50ce9a4
UD
272/* Restore ucontext (parm1) from stack. */
273 lwz r12,_FRAME_PARM_SAVE1(r1)
274 li r4,0
275 stw r3,_UC_REGS_PTR(r12)
276 addi r5,r12,_UC_SIGMASK
277 li r3,SIG_SETMASK
278 bl __sigprocmask@local
279 cmpwi r3,0
280 bne 3f /* L(error_exit) */
281
282 /*
283 * If the new ucontext refers to the point where we were interrupted
284 * by a signal, we have to use the rt_sigreturn system call to
285 * return to the context so we get both LR and CTR restored.
286 *
287 * Otherwise, the context we are restoring is either just after
288 * a procedure call (getcontext/swapcontext) or at the beginning
289 * of a procedure call (makecontext), so we don't need to restore
290 * r0, xer, ctr. We don't restore r2 since it will be used as
291 * the TLS pointer.
292 */
293 lwz r4,_FRAME_PARM_SAVE2(r1)
294 lwz r31,_UC_REGS_PTR(r4)
295 lwz r0,_UC_GREGS+(PT_MSR*4)(r31)
296 cmpwi r0,0
297 bne 4f /* L(do_sigret) */
298
299#ifdef __CONTEXT_ENABLE_FPRS
300# ifdef __CONTEXT_ENABLE_VRS
301
302# ifdef PIC
303 mflr r8
91d2a845
WS
304 SETUP_GOT_ACCESS(r7,got_label)
305 addis r7,r7,_GLOBAL_OFFSET_TABLE_-got_label@ha
306 addi r7,r7,_GLOBAL_OFFSET_TABLE_-got_label@l
a7e91561 307 mtlr r8
c50ce9a4
UD
308# ifdef SHARED
309 lwz r7,_rtld_global_ro@got(r7)
02f04a6c 310 lwz r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r7)
c50ce9a4
UD
311# else
312 lwz r7,_dl_hwcap@got(r7)
02f04a6c 313 lwz r7,LOWORD(r7)
c50ce9a4
UD
314# endif
315# else
02f04a6c
AM
316 lis r7,(_dl_hwcap+LOWORD)@ha
317 lwz r7,(_dl_hwcap+LOWORD)@l(r7)
c50ce9a4
UD
318# endif
319 andis. r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
320 la r10,(_UC_VREGS)(r31)
321 beq 6f /* L(has_no_vec) */
322
323 lwz r0,(32*16)(r10)
324 li r9,(32*16)
325 cmpwi r0,0
326 mtspr VRSAVE,r0
327 beq 6f /* L(has_no_vec) */
328
329 lvx v19,r9,r10
330 la r9,(16)(r10)
331
332 lvx v0,0,r10
333 lvx v1,0,r9
334 addi r10,r10,32
335 addi r9,r9,32
336
337 mtvscr v19
338 lvx v2,0,r10
339 lvx v3,0,r9
340 addi r10,r10,32
341 addi r9,r9,32
342
343 lvx v4,0,r10
344 lvx v5,0,r9
345 addi r10,r10,32
346 addi r9,r9,32
347
348 lvx v6,0,r10
349 lvx v7,0,r9
350 addi r10,r10,32
351 addi r9,r9,32
352
353 lvx v8,0,r10
354 lvx v9,0,r9
355 addi r10,r10,32
356 addi r9,r9,32
357
358 lvx v10,0,r10
359 lvx v11,0,r9
360 addi r10,r10,32
361 addi r9,r9,32
362
363 lvx v12,0,r10
364 lvx v13,0,r9
365 addi r10,r10,32
366 addi r9,r9,32
367
368 lvx v14,0,r10
369 lvx v15,0,r9
370 addi r10,r10,32
371 addi r9,r9,32
372
373 lvx v16,0,r10
374 lvx v17,0,r9
375 addi r10,r10,32
376 addi r9,r9,32
377
378 lvx v18,0,r10
379 lvx v19,0,r9
380 addi r10,r10,32
381 addi r9,r9,32
382
383 lvx v20,0,r10
384 lvx v21,0,r9
385 addi r10,r10,32
386 addi r9,r9,32
387
388 lvx v22,0,r10
389 lvx v23,0,r9
390 addi r10,r10,32
391 addi r9,r9,32
392
393 lvx v24,0,r10
394 lvx v25,0,r9
395 addi r10,r10,32
396 addi r9,r9,32
397
398 lvx v26,0,r10
399 lvx v27,0,r9
400 addi r10,r10,32
401 addi r9,r9,32
402
403 lvx v28,0,r10
404 lvx v29,0,r9
405 addi r10,r10,32
406 addi r9,r9,32
407
408 lvx v30,0,r10
409 lvx v31,0,r9
410 addi r10,r10,32
411 addi r9,r9,32
412
413 lvx v10,0,r10
414 lvx v11,0,r9
415
4166: /* L(has_no_vec): */
417# endif /* __CONTEXT_ENABLE_VRS */
418 /* Restore the floating-point registers */
419 lfd fp31,_UC_FREGS+(32*8)(r31)
420 lfd fp0,_UC_FREGS+(0*8)(r31)
edba7a54
UD
421# ifdef _ARCH_PWR6
422 /* Use the extended four-operand version of the mtfsf insn. */
b7219e53 423 mtfsf 0xff,fp31,1,0
edba7a54 424# else
bddec78c
UD
425 .machine push
426 .machine "power6"
edba7a54
UD
427 /* Availability of DFP indicates a 64-bit FPSCR. */
428 andi. r6,r7,PPC_FEATURE_HAS_DFP
429 beq 7f
430 /* Use the extended four-operand version of the mtfsf insn. */
431 mtfsf 0xff,fp31,1,0
432 b 8f
433 /* Continue to operate on the FPSCR as if it were 32-bits. */
4347: mtfsf 0xff,fp31
bddec78c 4358: .machine pop
edba7a54 436#endif /* _ARCH_PWR6 */
c50ce9a4
UD
437 lfd fp1,_UC_FREGS+(1*8)(r31)
438 lfd fp2,_UC_FREGS+(2*8)(r31)
439 lfd fp3,_UC_FREGS+(3*8)(r31)
440 lfd fp4,_UC_FREGS+(4*8)(r31)
441 lfd fp5,_UC_FREGS+(5*8)(r31)
442 lfd fp6,_UC_FREGS+(6*8)(r31)
443 lfd fp7,_UC_FREGS+(7*8)(r31)
444 lfd fp8,_UC_FREGS+(8*8)(r31)
445 lfd fp9,_UC_FREGS+(9*8)(r31)
446 lfd fp10,_UC_FREGS+(10*8)(r31)
447 lfd fp11,_UC_FREGS+(11*8)(r31)
448 lfd fp12,_UC_FREGS+(12*8)(r31)
449 lfd fp13,_UC_FREGS+(13*8)(r31)
450 lfd fp14,_UC_FREGS+(14*8)(r31)
451 lfd fp15,_UC_FREGS+(15*8)(r31)
452 lfd fp16,_UC_FREGS+(16*8)(r31)
453 lfd fp17,_UC_FREGS+(17*8)(r31)
454 lfd fp18,_UC_FREGS+(18*8)(r31)
455 lfd fp19,_UC_FREGS+(19*8)(r31)
456 lfd fp20,_UC_FREGS+(20*8)(r31)
457 lfd fp21,_UC_FREGS+(21*8)(r31)
458 lfd fp22,_UC_FREGS+(22*8)(r31)
459 lfd fp23,_UC_FREGS+(23*8)(r31)
460 lfd fp24,_UC_FREGS+(24*8)(r31)
461 lfd fp25,_UC_FREGS+(25*8)(r31)
462 lfd fp26,_UC_FREGS+(26*8)(r31)
463 lfd fp27,_UC_FREGS+(27*8)(r31)
464 lfd fp28,_UC_FREGS+(28*8)(r31)
465 lfd fp29,_UC_FREGS+(29*8)(r31)
466 lfd fp30,_UC_FREGS+(30*8)(r31)
467 lfd fp31,_UC_FREGS+(31*8)(r31)
468#endif /* __CONTEXT_ENABLE_FPRS */
469
cd78f7e7
JM
470#ifdef __CONTEXT_ENABLE_E500
471 setcontext_e500
472#endif
473
c50ce9a4
UD
474 /* Restore LR and CCR, and set CTR to the NIP value */
475 lwz r3,_UC_GREGS+(PT_LNK*4)(r31)
476 lwz r4,_UC_GREGS+(PT_NIP*4)(r31)
477 lwz r5,_UC_GREGS+(PT_CCR*4)(r31)
478 mtlr r3
479 mtctr r4
480 mtcr r5
481
482 /* Restore the general registers */
c50ce9a4
UD
483 lwz r3,_UC_GREGS+(PT_R3*4)(r31)
484 lwz r4,_UC_GREGS+(PT_R4*4)(r31)
485 lwz r5,_UC_GREGS+(PT_R5*4)(r31)
486 lwz r6,_UC_GREGS+(PT_R6*4)(r31)
487 lwz r7,_UC_GREGS+(PT_R7*4)(r31)
488 lwz r8,_UC_GREGS+(PT_R8*4)(r31)
489 lwz r9,_UC_GREGS+(PT_R9*4)(r31)
490 lwz r10,_UC_GREGS+(PT_R10*4)(r31)
491 lwz r11,_UC_GREGS+(PT_R11*4)(r31)
492 lwz r12,_UC_GREGS+(PT_R12*4)(r31)
493 lwz r13,_UC_GREGS+(PT_R13*4)(r31)
494 lwz r14,_UC_GREGS+(PT_R14*4)(r31)
495 lwz r15,_UC_GREGS+(PT_R15*4)(r31)
496 lwz r16,_UC_GREGS+(PT_R16*4)(r31)
497 lwz r17,_UC_GREGS+(PT_R17*4)(r31)
498 lwz r18,_UC_GREGS+(PT_R18*4)(r31)
499 lwz r19,_UC_GREGS+(PT_R19*4)(r31)
500 lwz r20,_UC_GREGS+(PT_R20*4)(r31)
501 lwz r21,_UC_GREGS+(PT_R21*4)(r31)
502 lwz r22,_UC_GREGS+(PT_R22*4)(r31)
503 lwz r23,_UC_GREGS+(PT_R23*4)(r31)
504 lwz r24,_UC_GREGS+(PT_R24*4)(r31)
505 lwz r25,_UC_GREGS+(PT_R25*4)(r31)
506 lwz r26,_UC_GREGS+(PT_R26*4)(r31)
507 lwz r27,_UC_GREGS+(PT_R27*4)(r31)
508 lwz r28,_UC_GREGS+(PT_R28*4)(r31)
509 lwz r29,_UC_GREGS+(PT_R29*4)(r31)
510 lwz r30,_UC_GREGS+(PT_R30*4)(r31)
a7e91561 511 lwz r1,_UC_GREGS+(PT_R1*4)(r31)
c50ce9a4
UD
512 lwz r31,_UC_GREGS+(PT_R31*4)(r31)
513
514 bctr
b7219e53 515
c50ce9a4
UD
5163:/*L(error_exit):*/
517 lwz r0,_FRAME_LR_SAVE+16(r1)
518 addi r1,r1,16
519 mtlr r0
520 blr
b7219e53 521
c50ce9a4
UD
5224:/*L(do_sigret):*/
523 addi r1,r4,-0xd0
524 li r0,SYS_ify(rt_sigreturn)
525 sc
526 /* NOTREACHED */
527
528END(__CONTEXT_FUNC_NAME)