elf: add note identifier for dlopen metadata
[glibc.git] / sysdeps / unix / sysv / linux / powerpc / powerpc32 / swapcontext-common.S
blob5a397d717106d4c2d9f5193e8f4c665e61d25676
1 /* Save current context and jump to a new context.
2    Copyright (C) 2005-2024 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, see
17    <https://www.gnu.org/licenses/>.  */
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.  */
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
37 #ifdef __CONTEXT_ENABLE_VRS
38         .machine        "altivec"
39 #endif
40 ENTRY(__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         stw     r4,_FRAME_PARM_SAVE2(r1)        /* new context pointer */
47         clrrwi  r3,r3,4
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         cfi_offset (lr, _FRAME_LR_SAVE)
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)
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)
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)
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)
146 # ifdef PIC
147         mflr    r8
148 #  define got_label GENERATE_GOT_LABEL (__CONTEXT_FUNC_NAME)
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
152 #  ifdef SHARED
153         lwz     r7,_rtld_global_ro@got(r7)
154         mtlr    r8
155         lwz     r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r7)
156 #  else
157         lwz     r7,_dl_hwcap@got(r7)
158         mtlr    r8
159         lwz     r7,LOWORD(r7)
160 #  endif
161 # else
162         lis     r7,(_dl_hwcap+LOWORD)@ha
163         lwz     r7,(_dl_hwcap+LOWORD)@l(r7)
164 # endif
166 # ifdef __CONTEXT_ENABLE_VRS
167         andis.  r6,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
169         la      r10,(_UC_VREGS)(r3)
170         la      r9,(_UC_VREGS+16)(r3)
172 /*      beq     L(no_vec)*/
173         beq     2f
174 /* address of the combined VSCR/VSAVE quadword.  */
175         la      r8,(_UC_VREGS+512)(r3)
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
187         stvx  v2,0,r10
188         stvx  v3,0,r9
189         addi  r10,r10,32
190         addi  r9,r9,32
192         stvx    v0,0,r8
194         stvx  v4,0,r10
195         stvx  v5,0,r9
196         addi  r10,r10,32
197         addi  r9,r9,32
199         stvx  v6,0,r10
200         stvx  v7,0,r9
201         addi  r10,r10,32
202         addi  r9,r9,32
204         stvx  v8,0,r10
205         stvx  v9,0,r9
206         addi  r10,r10,32
207         addi  r9,r9,32
209         stvx  v10,0,r10
210         stvx  v11,0,r9
211         addi  r10,r10,32
212         addi  r9,r9,32
214         stvx  v12,0,r10
215         stvx  v13,0,r9
216         addi  r10,r10,32
217         addi  r9,r9,32
219         stvx  v14,0,r10
220         stvx  v15,0,r9
221         addi  r10,r10,32
222         addi  r9,r9,32
224         stvx  v16,0,r10
225         stvx  v17,0,r9
226         addi  r10,r10,32
227         addi  r9,r9,32
229         stvx  v18,0,r10
230         stvx  v19,0,r9
231         addi  r10,r10,32
232         addi  r9,r9,32
234         stvx  v20,0,r10
235         stvx  v21,0,r9
236         addi  r10,r10,32
237         addi  r9,r9,32
239         stvx  v22,0,r10
240         stvx  v23,0,r9
241         addi  r10,r10,32
242         addi  r9,r9,32
244         stvx  v24,0,r10
245         stvx  v25,0,r9
246         addi  r10,r10,32
247         addi  r9,r9,32
249         stvx  v26,0,r10
250         stvx  v27,0,r9
251         addi  r10,r10,32
252         addi  r9,r9,32
254         stvx  v28,0,r10
255         stvx  v29,0,r9
256         addi  r10,r10,32
257         addi  r9,r9,32
259         mfvscr  v0
260         stvx  v30,0,r10
261         stvx  v31,0,r9
262         stw     r0,0(r8)
264 2: /*L(no_vec):*/
265 # endif /* __CONTEXT_ENABLE_VRS */
266 #endif /* __CONTEXT_ENABLE_FPRS */
268 /* Restore ucontext (parm1) from stack.  */
269         lwz     r12,_FRAME_PARM_SAVE1(r1)
270         lwz     r4,_FRAME_PARM_SAVE2(r1)
271         addi    r4,r4,_UC_SIGMASK
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         lwz     r4,_FRAME_PARM_SAVE2(r1)
280         lwz     r31,_UC_REGS_PTR(r4)
282 #ifdef __CONTEXT_ENABLE_FPRS
283 # ifdef __CONTEXT_ENABLE_VRS
285 #  ifdef PIC
286         mflr    r8
287         SETUP_GOT_ACCESS(r7,got_label)
288         addis   r7,r7,_GLOBAL_OFFSET_TABLE_-got_label@ha
289         addi    r7,r7,_GLOBAL_OFFSET_TABLE_-got_label@l
290         mtlr    r8
291 #   ifdef SHARED
292         lwz     r7,_rtld_global_ro@got(r7)
293         lwz     r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r7)
294 #   else
295         lwz     r7,_dl_hwcap@got(r7)
296         lwz     r7,LOWORD(r7)
297 #   endif
298 #  else
299         lis     r7,(_dl_hwcap+LOWORD)@ha
300         lwz     r7,(_dl_hwcap+LOWORD)@l(r7)
301 #  endif
302         andis.  r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
303         la      r10,(_UC_VREGS)(r31)
304         beq     6f      /* L(has_no_vec) */
306         lwz   r0,(32*16)(r10)
307         li    r9,(32*16)
308         cmpwi r0,0
309         mtspr VRSAVE,r0
310         beq     6f      /* L(has_no_vec) */
312         lvx   v19,r9,r10
313         la    r9,(16)(r10)
315         lvx   v0,0,r10
316         lvx   v1,0,r9
317         addi  r10,r10,32
318         addi  r9,r9,32
320         mtvscr  v19
321         lvx   v2,0,r10
322         lvx   v3,0,r9
323         addi  r10,r10,32
324         addi  r9,r9,32
326         lvx   v4,0,r10
327         lvx   v5,0,r9
328         addi  r10,r10,32
329         addi  r9,r9,32
331         lvx   v6,0,r10
332         lvx   v7,0,r9
333         addi  r10,r10,32
334         addi  r9,r9,32
336         lvx   v8,0,r10
337         lvx   v9,0,r9
338         addi  r10,r10,32
339         addi  r9,r9,32
341         lvx   v10,0,r10
342         lvx   v11,0,r9
343         addi  r10,r10,32
344         addi  r9,r9,32
346         lvx   v12,0,r10
347         lvx   v13,0,r9
348         addi  r10,r10,32
349         addi  r9,r9,32
351         lvx   v14,0,r10
352         lvx   v15,0,r9
353         addi  r10,r10,32
354         addi  r9,r9,32
356         lvx   v16,0,r10
357         lvx   v17,0,r9
358         addi  r10,r10,32
359         addi  r9,r9,32
361         lvx   v18,0,r10
362         lvx   v19,0,r9
363         addi  r10,r10,32
364         addi  r9,r9,32
366         lvx   v20,0,r10
367         lvx   v21,0,r9
368         addi  r10,r10,32
369         addi  r9,r9,32
371         lvx   v22,0,r10
372         lvx   v23,0,r9
373         addi  r10,r10,32
374         addi  r9,r9,32
376         lvx   v24,0,r10
377         lvx   v25,0,r9
378         addi  r10,r10,32
379         addi  r9,r9,32
381         lvx   v26,0,r10
382         lvx   v27,0,r9
383         addi  r10,r10,32
384         addi  r9,r9,32
386         lvx   v28,0,r10
387         lvx   v29,0,r9
388         addi  r10,r10,32
389         addi  r9,r9,32
391         lvx   v30,0,r10
392         lvx   v31,0,r9
393         addi  r10,r10,32
394         addi  r9,r9,32
396         lvx   v10,0,r10
397         lvx   v11,0,r9
399 6: /* L(has_no_vec): */
400 # endif /* __CONTEXT_ENABLE_VRS */
401         /* Restore the floating-point registers */
402         lfd     fp31,_UC_FREGS+(32*8)(r31)
403         lfd     fp0,_UC_FREGS+(0*8)(r31)
404 # ifdef _ARCH_PWR6
405         /* Use the extended four-operand version of the mtfsf insn.  */
406         mtfsf   0xff,fp31,1,0
407 # else
408         .machine push
409         .machine "power6"
410         /* Availability of DFP indicates a 64-bit FPSCR.  */
411         andi.   r6,r7,PPC_FEATURE_HAS_DFP
412         beq     7f
413         /* Use the extended four-operand version of the mtfsf insn.  */
414         mtfsf   0xff,fp31,1,0
415         b       8f
416         /* Continue to operate on the FPSCR as if it were 32-bits.  */
417 7:      mtfsf   0xff,fp31
418 8:      .machine pop
419 #endif /* _ARCH_PWR6 */
420         lfd     fp1,_UC_FREGS+(1*8)(r31)
421         lfd     fp2,_UC_FREGS+(2*8)(r31)
422         lfd     fp3,_UC_FREGS+(3*8)(r31)
423         lfd     fp4,_UC_FREGS+(4*8)(r31)
424         lfd     fp5,_UC_FREGS+(5*8)(r31)
425         lfd     fp6,_UC_FREGS+(6*8)(r31)
426         lfd     fp7,_UC_FREGS+(7*8)(r31)
427         lfd     fp8,_UC_FREGS+(8*8)(r31)
428         lfd     fp9,_UC_FREGS+(9*8)(r31)
429         lfd     fp10,_UC_FREGS+(10*8)(r31)
430         lfd     fp11,_UC_FREGS+(11*8)(r31)
431         lfd     fp12,_UC_FREGS+(12*8)(r31)
432         lfd     fp13,_UC_FREGS+(13*8)(r31)
433         lfd     fp14,_UC_FREGS+(14*8)(r31)
434         lfd     fp15,_UC_FREGS+(15*8)(r31)
435         lfd     fp16,_UC_FREGS+(16*8)(r31)
436         lfd     fp17,_UC_FREGS+(17*8)(r31)
437         lfd     fp18,_UC_FREGS+(18*8)(r31)
438         lfd     fp19,_UC_FREGS+(19*8)(r31)
439         lfd     fp20,_UC_FREGS+(20*8)(r31)
440         lfd     fp21,_UC_FREGS+(21*8)(r31)
441         lfd     fp22,_UC_FREGS+(22*8)(r31)
442         lfd     fp23,_UC_FREGS+(23*8)(r31)
443         lfd     fp24,_UC_FREGS+(24*8)(r31)
444         lfd     fp25,_UC_FREGS+(25*8)(r31)
445         lfd     fp26,_UC_FREGS+(26*8)(r31)
446         lfd     fp27,_UC_FREGS+(27*8)(r31)
447         lfd     fp28,_UC_FREGS+(28*8)(r31)
448         lfd     fp29,_UC_FREGS+(29*8)(r31)
449         lfd     fp30,_UC_FREGS+(30*8)(r31)
450         lfd     fp31,_UC_FREGS+(31*8)(r31)
451 #endif /* __CONTEXT_ENABLE_FPRS */
453         /* Restore LR and CCR, and set CTR to the NIP value */
454         lwz     r3,_UC_GREGS+(PT_LNK*4)(r31)
455         lwz     r4,_UC_GREGS+(PT_NIP*4)(r31)
456         lwz     r5,_UC_GREGS+(PT_CCR*4)(r31)
457         mtlr    r3
458         mtctr   r4
459         mtcr    r5
461         /* Restore the general registers */
462         lwz     r3,_UC_GREGS+(PT_R3*4)(r31)
463         lwz     r4,_UC_GREGS+(PT_R4*4)(r31)
464         lwz     r5,_UC_GREGS+(PT_R5*4)(r31)
465         lwz     r6,_UC_GREGS+(PT_R6*4)(r31)
466         lwz     r7,_UC_GREGS+(PT_R7*4)(r31)
467         lwz     r8,_UC_GREGS+(PT_R8*4)(r31)
468         lwz     r9,_UC_GREGS+(PT_R9*4)(r31)
469         lwz     r10,_UC_GREGS+(PT_R10*4)(r31)
470         lwz     r11,_UC_GREGS+(PT_R11*4)(r31)
471         lwz     r12,_UC_GREGS+(PT_R12*4)(r31)
472         lwz     r13,_UC_GREGS+(PT_R13*4)(r31)
473         lwz     r14,_UC_GREGS+(PT_R14*4)(r31)
474         lwz     r15,_UC_GREGS+(PT_R15*4)(r31)
475         lwz     r16,_UC_GREGS+(PT_R16*4)(r31)
476         lwz     r17,_UC_GREGS+(PT_R17*4)(r31)
477         lwz     r18,_UC_GREGS+(PT_R18*4)(r31)
478         lwz     r19,_UC_GREGS+(PT_R19*4)(r31)
479         lwz     r20,_UC_GREGS+(PT_R20*4)(r31)
480         lwz     r21,_UC_GREGS+(PT_R21*4)(r31)
481         lwz     r22,_UC_GREGS+(PT_R22*4)(r31)
482         lwz     r23,_UC_GREGS+(PT_R23*4)(r31)
483         lwz     r24,_UC_GREGS+(PT_R24*4)(r31)
484         lwz     r25,_UC_GREGS+(PT_R25*4)(r31)
485         lwz     r26,_UC_GREGS+(PT_R26*4)(r31)
486         lwz     r27,_UC_GREGS+(PT_R27*4)(r31)
487         lwz     r28,_UC_GREGS+(PT_R28*4)(r31)
488         lwz     r29,_UC_GREGS+(PT_R29*4)(r31)
489         lwz     r30,_UC_GREGS+(PT_R30*4)(r31)
490         lwz     r1,_UC_GREGS+(PT_R1*4)(r31)
491         lwz     r31,_UC_GREGS+(PT_R31*4)(r31)
493         bctr
495 3:/*L(error_exit):*/
496         lwz     r0,_FRAME_LR_SAVE+16(r1)
497         addi    r1,r1,16
498         mtlr    r0
499         blr
501 END(__CONTEXT_FUNC_NAME)