Update copyright notices with scripts/update-copyrights.
[glibc.git] / sysdeps / unix / sysv / linux / powerpc / powerpc32 / makecontext.S
blob95902b13f97b1f1b1877a9889d2019da846f1306
1 /* Set up a context to call a function.
2    Copyright (C) 2002-2013 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    <http://www.gnu.org/licenses/>.  */
19 #include <sysdep.h>
20 #include <shlib-compat.h>
22 #define __ASSEMBLY__
23 #include <asm/ptrace.h>
24 #include "ucontext_i.h"
26 ENTRY(__makecontext)
27         /* Set up the first 7 args to the function in its registers */
28         lwz     r11,_UC_REGS_PTR(r3)
29         stw     r6,_UC_GREGS+(PT_R3*4)(r11)
30         stw     r7,_UC_GREGS+(PT_R4*4)(r11)
31         stw     r8,_UC_GREGS+(PT_R5*4)(r11)
32         stw     r9,_UC_GREGS+(PT_R6*4)(r11)
33         stw     r10,_UC_GREGS+(PT_R7*4)(r11)
34         lwz     r8,8(r1)
35         lwz     r9,12(r1)
36         stw     r8,_UC_GREGS+(PT_R8*4)(r11)
37         stw     r9,_UC_GREGS+(PT_R9*4)(r11)
39         /* Set the NIP to the start of the function */
40         stw     r4,_UC_GREGS+(PT_NIP*4)(r11)
42         /* Set the function's r31 to ucp->uc_link for the exitcode below. */
43         lwz     r7,_UC_LINK(r3)
44         stw     r7,_UC_GREGS+(PT_R31*4)(r11)
46         /* Set the function's LR to point to the exitcode below. */
47 #ifdef PIC
48         mflr    r0
49         cfi_register(lr,r0)
50         bl      1f
51 1:      mflr    r6
52         addi    r6,r6,L(exitcode)-1b
53         mtlr    r0
54         cfi_same_value (lr)
55 #else
56         lis     r6,L(exitcode)@ha
57         addi    r6,r6,L(exitcode)@l
58 #endif
59         stw     r6,_UC_GREGS+(PT_LNK*4)(r11)
61         /*
62          * Set up the stack frame for the function.
63          * If we have more than 5 args to the function (8 args to makecontext),
64          * there will be some arguments on the stack which have to end up
65          * in registers.  If there are more than 8 args to the function,
66          * we have to copy (argc - 8) args from our stack to the functions'
67          * stack (and allow space for them in the frame).
68          */
69         lwz     r4,_UC_STACK_SP(r3)
70         lwz     r8,_UC_STACK_SIZE(r3)
71         add     r4,r4,r8
72         rlwinm  r4,r4,0,0,27    /* round down to 16-byte boundary */
73         addi    r7,r4,-16       /* stack frame for fn's caller */
74         cmpwi   r5,8
75         blt     2f              /* less than 8 args is easy */
76         lwz     r10,16(r1)
77         stw     r10,_UC_GREGS+(PT_R10*4)(r11)
78         beq     2f              /* if exactly 8 args */
79         subi    r9,r5,3
80         subi    r5,r5,8
81         rlwinm  r9,r9,2,0,27
82         subf    r7,r9,r4
83         mtctr   r5              /* copy the 9th and following args */
84         addi    r6,r1,16
85         addi    r8,r7,4
86 3:      lwzu    r10,4(r6)
87         stwu    r10,4(r8)
88         bdnz    3b
89 2:      stw     r7,_UC_GREGS+(PT_R1*4)(r11)
90         li      r6,0
91         stw     r6,0(r7)
93         blr
96  * If the function returns, it comes here.  We put ucp->uc_link in
97  * r31, which is a callee-saved register.  We have to continue with
98  * the context that r31 points to, or exit if it is 0.
99  */
100 L(exitcode):
101         mr.     r3,r31
102         beq     4f
103         bl      __setcontext@local
104 4:      bl      HIDDEN_JUMPTARGET(exit)
105         b       4b
107 END(__makecontext)
109 versioned_symbol (libc, __makecontext, makecontext, GLIBC_2_3_4)
111 #if SHLIB_COMPAT (libc, GLIBC_2_3_3, GLIBC_2_3_4)
113         compat_text_section
114 ENTRY(__novec_makecontext)
115         /* Set up the first 7 args to the function in its registers */
116         addi    r11,r3,_UC_REG_SPACE
117         stw     r11,_UC_REGS_PTR(r3)
118         stw     r6,_UC_GREGS+(PT_R3*4)(r11)
119         stw     r7,_UC_GREGS+(PT_R4*4)(r11)
120         stw     r8,_UC_GREGS+(PT_R5*4)(r11)
121         stw     r9,_UC_GREGS+(PT_R6*4)(r11)
122         stw     r10,_UC_GREGS+(PT_R7*4)(r11)
123         lwz     r8,8(r1)
124         lwz     r9,12(r1)
125         stw     r8,_UC_GREGS+(PT_R8*4)(r11)
126         stw     r9,_UC_GREGS+(PT_R9*4)(r11)
128         /* Set the NIP to the start of the function */
129         stw     r4,_UC_GREGS+(PT_NIP*4)(r11)
131         /* Set the function's r31 to ucp->uc_link for the exitcode below. */
132         lwz     r7,_UC_LINK(r3)
133         stw     r7,_UC_GREGS+(PT_R31*4)(r11)
135         /* Set the function's LR to point to the exitcode below. */
136 #ifdef PIC
137         mflr    r0
138         cfi_register(lr,r0)
139         bl      1f
140 1:      mflr    r6
141         addi    r6,r6,L(novec_exitcode)-1b
142         mtlr    r0
143         cfi_same_value (lr)
144 #else
145         lis     r6,L(novec_exitcode)@ha
146         addi    r6,r6,L(novec_exitcode)@l
147 #endif
148         stw     r6,_UC_GREGS+(PT_LNK*4)(r11)
150         /*
151          * Set up the stack frame for the function.
152          * If we have more than 5 args to the function (8 args to makecontext),
153          * there will be some arguments on the stack which have to end up
154          * in registers.  If there are more than 8 args to the function,
155          * we have to copy (argc - 8) args from our stack to the functions'
156          * stack (and allow space for them in the frame).
157          */
158         lwz     r4,_UC_STACK_SP(r3)
159         lwz     r8,_UC_STACK_SIZE(r3)
160         add     r4,r4,r8
161         rlwinm  r4,r4,0,0,27    /* round down to 16-byte boundary */
162         addi    r7,r4,-16       /* stack frame for fn's caller */
163         cmpwi   r5,8
164         blt     2f              /* less than 8 args is easy */
165         lwz     r10,16(r1)
166         stw     r10,_UC_GREGS+(PT_R10*4)(r11)
167         beq     2f              /* if exactly 8 args */
168         subi    r9,r5,3
169         subi    r5,r5,8
170         rlwinm  r9,r9,2,0,27
171         subf    r7,r9,r4
172         mtctr   r5              /* copy the 9th and following args */
173         addi    r6,r1,16
174         addi    r8,r7,4
175 3:      lwzu    r10,4(r6)
176         stwu    r10,4(r8)
177         bdnz    3b
178 2:      stw     r7,_UC_GREGS+(PT_R1*4)(r11)
179         li      r6,0
180         stw     r6,0(r7)
182         blr
185  * If the function returns, it comes here.  We put ucp->uc_link in
186  * r31, which is a callee-saved register.  We have to continue with
187  * the context that r31 points to, or exit if it is 0.
188  */
189 L(novec_exitcode):
190         mr.     r3,r31
191         beq     4f
192         bl      __novec_setcontext@local
193 4:      bl      HIDDEN_JUMPTARGET(exit)
194         b       4b
196 END(__novec_makecontext)
197         .previous
199 compat_symbol (libc, __novec_makecontext, makecontext, GLIBC_2_3_3)
200 #endif
202 #if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_3_3)
204 #define _ERRNO_H        1
205 #include <bits/errno.h>
207         compat_text_section
208 ENTRY (__makecontext_stub)
209         li      r3,ENOSYS
210         b       __syscall_error@local
211 END (__makecontext_stub)
212         .previous
214 compat_symbol (libc, __makecontext_stub, makecontext, GLIBC_2_1)
216 #endif