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