]>
Commit | Line | Data |
---|---|---|
c50ce9a4 | 1 | /* Save current context, powerpc32 common. |
b168057a | 2 | Copyright (C) 2005-2015 Free Software Foundation, Inc. |
c50ce9a4 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/>. */ | |
c50ce9a4 UD |
18 | |
19 | /* This is the common implementation of getcontext for powerpc32. | |
929d11c7 | 20 | It not complete in itself should be included in to a framework that |
c50ce9a4 UD |
21 | defines: |
22 | __CONTEXT_FUNC_NAME | |
23 | and if appropriate: | |
24 | __CONTEXT_ENABLE_FPRS | |
25 | __CONTEXT_ENABLE_VRS | |
6f65e668 | 26 | Any architecture that implements the Vector unit is assumed to also |
c50ce9a4 UD |
27 | implement the floating unit. */ |
28 | ||
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 | |
36 | ||
37 | #ifdef __CONTEXT_ENABLE_VRS | |
38 | .machine "altivec" | |
39 | #endif | |
40 | ENTRY(__CONTEXT_FUNC_NAME) | |
41 | stwu r1,-16(r1) | |
a7e91561 | 42 | cfi_adjust_cfa_offset (16) |
c50ce9a4 UD |
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 | clrrwi r3,r3,4 | |
47 | ||
48 | /* Save the general purpose registers */ | |
49 | stw r0,_UC_GREGS+(PT_R0*4)(r3) | |
50 | mflr r0 | |
51 | stw r2,_UC_GREGS+(PT_R2*4)(r3) | |
52 | stw r4,_UC_GREGS+(PT_R4*4)(r3) | |
53 | /* Set the callers LR_SAVE, and the ucontext LR and NIP to the callers | |
54 | return address. */ | |
55 | stw r0,_UC_GREGS+(PT_LNK*4)(r3) | |
56 | stw r0,_UC_GREGS+(PT_NIP*4)(r3) | |
57 | stw r0,_FRAME_LR_SAVE+16(r1) | |
a7e91561 | 58 | cfi_offset (lr, _FRAME_LR_SAVE) |
c50ce9a4 UD |
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 | /* Save the value of R1. We had to push the stack before we | |
87 | had the address of uc_reg_space. So compute the address of | |
88 | the callers stack pointer and save it as R1. */ | |
89 | addi r8,r1,16 | |
90 | li r0,0 | |
91 | /* Save the count, exception and condition registers. */ | |
92 | mfctr r11 | |
93 | mfxer r10 | |
94 | mfcr r9 | |
95 | stw r8,_UC_GREGS+(PT_R1*4)(r3) | |
96 | stw r11,_UC_GREGS+(PT_CTR*4)(r3) | |
97 | stw r10,_UC_GREGS+(PT_XER*4)(r3) | |
98 | stw r9,_UC_GREGS+(PT_CCR*4)(r3) | |
99 | /* Set the return value of getcontext to "success". R3 is the only | |
100 | register whose value is not preserved in the saved context. */ | |
101 | stw r0,_UC_GREGS+(PT_R3*4)(r3) | |
102 | ||
103 | /* Zero fill fields that can't be set in user state. */ | |
104 | stw r0,_UC_GREGS+(PT_MSR*4)(r3) | |
105 | stw r0,_UC_GREGS+(PT_MQ*4)(r3) | |
106 | ||
107 | #ifdef __CONTEXT_ENABLE_FPRS | |
108 | /* Save the floating-point registers */ | |
109 | stfd fp0,_UC_FREGS+(0*8)(r3) | |
110 | stfd fp1,_UC_FREGS+(1*8)(r3) | |
111 | stfd fp2,_UC_FREGS+(2*8)(r3) | |
112 | stfd fp3,_UC_FREGS+(3*8)(r3) | |
113 | stfd fp4,_UC_FREGS+(4*8)(r3) | |
114 | stfd fp5,_UC_FREGS+(5*8)(r3) | |
115 | stfd fp6,_UC_FREGS+(6*8)(r3) | |
116 | stfd fp7,_UC_FREGS+(7*8)(r3) | |
117 | stfd fp8,_UC_FREGS+(8*8)(r3) | |
118 | stfd fp9,_UC_FREGS+(9*8)(r3) | |
119 | stfd fp10,_UC_FREGS+(10*8)(r3) | |
120 | stfd fp11,_UC_FREGS+(11*8)(r3) | |
121 | stfd fp12,_UC_FREGS+(12*8)(r3) | |
122 | stfd fp13,_UC_FREGS+(13*8)(r3) | |
123 | stfd fp14,_UC_FREGS+(14*8)(r3) | |
124 | stfd fp15,_UC_FREGS+(15*8)(r3) | |
125 | stfd fp16,_UC_FREGS+(16*8)(r3) | |
126 | stfd fp17,_UC_FREGS+(17*8)(r3) | |
127 | stfd fp18,_UC_FREGS+(18*8)(r3) | |
128 | stfd fp19,_UC_FREGS+(19*8)(r3) | |
129 | stfd fp20,_UC_FREGS+(20*8)(r3) | |
130 | stfd fp21,_UC_FREGS+(21*8)(r3) | |
131 | stfd fp22,_UC_FREGS+(22*8)(r3) | |
132 | stfd fp23,_UC_FREGS+(23*8)(r3) | |
133 | stfd fp24,_UC_FREGS+(24*8)(r3) | |
134 | stfd fp25,_UC_FREGS+(25*8)(r3) | |
135 | stfd fp26,_UC_FREGS+(26*8)(r3) | |
136 | stfd fp27,_UC_FREGS+(27*8)(r3) | |
137 | stfd fp28,_UC_FREGS+(28*8)(r3) | |
138 | stfd fp29,_UC_FREGS+(29*8)(r3) | |
139 | mffs fp0 | |
140 | stfd fp30,_UC_FREGS+(30*8)(r3) | |
141 | stfd fp31,_UC_FREGS+(31*8)(r3) | |
142 | stfd fp0,_UC_FREGS+(32*8)(r3) | |
143 | ||
144 | # ifdef __CONTEXT_ENABLE_VRS | |
145 | # ifdef PIC | |
146 | mflr r8 | |
929d11c7 | 147 | # define got_label GENERATE_GOT_LABEL (__CONTEXT_FUNC_NAME) |
91d2a845 WS |
148 | SETUP_GOT_ACCESS(r7,got_label) |
149 | addis r7,r7,_GLOBAL_OFFSET_TABLE_-got_label@ha | |
150 | addi r7,r7,_GLOBAL_OFFSET_TABLE_-got_label@l | |
c50ce9a4 UD |
151 | # ifdef SHARED |
152 | lwz r7,_rtld_global_ro@got(r7) | |
153 | mtlr r8 | |
02f04a6c | 154 | lwz r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r7) |
c50ce9a4 UD |
155 | # else |
156 | lwz r7,_dl_hwcap@got(r7) | |
157 | mtlr r8 | |
02f04a6c | 158 | lwz r7,LOWORD(r7) |
c50ce9a4 UD |
159 | # endif |
160 | # else | |
02f04a6c AM |
161 | lis r7,(_dl_hwcap+LOWORD)@ha |
162 | lwz r7,(_dl_hwcap+LOWORD)@l(r7) | |
c50ce9a4 UD |
163 | # endif |
164 | andis. r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16) | |
165 | ||
166 | la r10,(_UC_VREGS)(r3) | |
167 | la r9,(_UC_VREGS+16)(r3) | |
929d11c7 | 168 | |
c50ce9a4 | 169 | beq 2f /* L(no_vec) */ |
929d11c7 | 170 | /* address of the combined VSCR/VSAVE quadword. */ |
c50ce9a4 UD |
171 | la r8,(_UC_VREGS+512)(r3) |
172 | ||
173 | /* Save the vector registers */ | |
174 | stvx v0,0,r10 | |
175 | stvx v1,0,r9 | |
176 | addi r10,r10,32 | |
177 | addi r9,r9,32 | |
178 | /* We need to get the Vector Status and Control Register early to avoid | |
179 | store order problems later with the VSAVE register that shares the | |
180 | same quadword. */ | |
181 | mfvscr v0 | |
182 | ||
183 | stvx v2,0,r10 | |
184 | stvx v3,0,r9 | |
185 | addi r10,r10,32 | |
186 | addi r9,r9,32 | |
187 | ||
188 | stvx v0,0,r8 | |
929d11c7 | 189 | |
c50ce9a4 UD |
190 | stvx v4,0,r10 |
191 | stvx v5,0,r9 | |
192 | addi r10,r10,32 | |
193 | addi r9,r9,32 | |
194 | ||
195 | stvx v6,0,r10 | |
196 | stvx v7,0,r9 | |
197 | addi r10,r10,32 | |
198 | addi r9,r9,32 | |
199 | ||
200 | stvx v8,0,r10 | |
201 | stvx v9,0,r9 | |
202 | addi r10,r10,32 | |
203 | addi r9,r9,32 | |
204 | ||
205 | stvx v10,0,r10 | |
206 | stvx v11,0,r9 | |
207 | addi r10,r10,32 | |
208 | addi r9,r9,32 | |
209 | ||
210 | stvx v12,0,r10 | |
211 | stvx v13,0,r9 | |
212 | addi r10,r10,32 | |
213 | addi r9,r9,32 | |
214 | ||
215 | stvx v14,0,r10 | |
216 | stvx v15,0,r9 | |
217 | addi r10,r10,32 | |
218 | addi r9,r9,32 | |
219 | ||
220 | stvx v16,0,r10 | |
221 | stvx v17,0,r9 | |
222 | addi r10,r10,32 | |
223 | addi r9,r9,32 | |
224 | ||
225 | stvx v18,0,r10 | |
226 | stvx v19,0,r9 | |
227 | addi r10,r10,32 | |
228 | addi r9,r9,32 | |
229 | ||
230 | stvx v20,0,r10 | |
231 | stvx v21,0,r9 | |
232 | addi r10,r10,32 | |
233 | addi r9,r9,32 | |
234 | ||
235 | stvx v22,0,r10 | |
236 | stvx v23,0,r9 | |
237 | addi r10,r10,32 | |
238 | addi r9,r9,32 | |
239 | ||
240 | stvx v24,0,r10 | |
241 | stvx v25,0,r9 | |
242 | addi r10,r10,32 | |
243 | addi r9,r9,32 | |
244 | ||
245 | stvx v26,0,r10 | |
246 | stvx v27,0,r9 | |
247 | addi r10,r10,32 | |
248 | addi r9,r9,32 | |
249 | ||
250 | stvx v28,0,r10 | |
251 | stvx v29,0,r9 | |
252 | addi r10,r10,32 | |
253 | addi r9,r9,32 | |
254 | ||
255 | mfspr r0,VRSAVE | |
256 | stvx v30,0,r10 | |
257 | stvx v31,0,r9 | |
258 | ||
259 | stw r0,0(r8) | |
260 | ||
261 | 2: /* L(no_vec): */ | |
262 | # endif | |
263 | #endif | |
cd78f7e7 JM |
264 | |
265 | #ifdef __CONTEXT_ENABLE_E500 | |
266 | getcontext_e500 | |
267 | #endif | |
268 | ||
c50ce9a4 UD |
269 | /* We need to set up parms and call sigprocmask which will clobber |
270 | volatile registers. So before the call we need to retrieve the | |
271 | original ucontext ptr (parm1) from stack and store the UC_REGS_PTR | |
272 | (current R3). */ | |
273 | lwz r12,_FRAME_PARM_SAVE1(r1) | |
274 | li r4,0 | |
275 | stw r3,_UC_REGS_PTR(r12) | |
276 | addi r5,r12,_UC_SIGMASK | |
277 | li r3,SIG_BLOCK | |
278 | bl __sigprocmask@local | |
279 | ||
280 | lwz r0,_FRAME_LR_SAVE+16(r1) | |
281 | addi r1,r1,16 | |
282 | mtlr r0 | |
283 | blr | |
284 | END(__CONTEXT_FUNC_NAME) |