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