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