Cygwin: access: Fix X_OK behaviour for backup operators and admins
[newlib-cygwin.git] / newlib / libc / machine / powerpc / setjmp.S
blobc7af5b1054ef64b8bc4397e8b49c31548957f792
1 /* This is a simple version of setjmp and longjmp for the PowerPC.
2    Ian Lance Taylor, Cygnus Support, 9 Feb 1994.  
3    Modified by Jeff Johnston, Red Hat Inc. 2 Oct 2001.
4    Modified by Sebastian Huber, embedded brains GmbH. 22 Sep 2022.  */
6 #include "ppc-asm.h"
8 FUNC_START(setjmp)
9 #ifdef __ALTIVEC__
10         addi    3,3,15          # align Altivec to 16 byte boundary
11 #if __powerpc64__
12         clrrdi  3,3,4
13 #else
14         rlwinm  3,3,0,0,27
15 #endif
16 #else
17         addi    3,3,7           # align to 8 byte boundary
18 #if __powerpc64__
19         clrrdi  3,3,3
20 #else
21         rlwinm  3,3,0,0,28
22 #endif
23 #endif
24 #if __SPE__
25         /* If we are E500, then save 64-bit registers.  */
26         evstdd  1,0(3)          # offset 0
27         evstdd  2,8(3)          # offset 8
28         evstdd  13,16(3)        # offset 16
29         evstdd  14,24(3)        # offset 24
30         evstdd  15,32(3)        # offset 32
31         evstdd  16,40(3)        # offset 40
32         evstdd  17,48(3)        # offset 48
33         evstdd  18,56(3)        # offset 56
34         evstdd  19,64(3)        # offset 64
35         evstdd  20,72(3)        # offset 72
36         evstdd  21,80(3)        # offset 80
37         evstdd  22,88(3)        # offset 88
38         evstdd  23,96(3)        # offset 96
39         evstdd  24,104(3)       # offset 104
40         evstdd  25,112(3)       # offset 112
41         evstdd  26,120(3)       # offset 120
42         evstdd  27,128(3)       # offset 128
43         evstdd  28,136(3)       # offset 136
44         evstdd  29,144(3)       # offset 144
45         evstdd  30,152(3)       # offset 152
46         evstdd  31,160(3)       # offset 160
48         /* Add 164 to r3 to account for the amount of data we just
49            stored.  Note that we are not adding 168 because the next
50            store instruction uses an offset of 4.  */
51         addi    3,3,164
52 #elif __powerpc64__
53         /* In the first store, add 8 to r3 so that the subsequent floating
54            point stores are aligned on an 8 byte boundary and the Altivec
55            stores are aligned on a 16 byte boundary.  */
56         stdu    1,8(3)          # offset 8
57         stdu    2,8(3)          # offset 16
58         stdu    13,8(3)         # offset 24
59         stdu    14,8(3)         # offset 32
60         stdu    15,8(3)         # offset 40
61         stdu    16,8(3)         # offset 48
62         stdu    17,8(3)         # offset 56
63         stdu    18,8(3)         # offset 64
64         stdu    19,8(3)         # offset 72
65         stdu    20,8(3)         # offset 80
66         stdu    21,8(3)         # offset 88
67         stdu    22,8(3)         # offset 96
68         stdu    23,8(3)         # offset 104
69         stdu    24,8(3)         # offset 112
70         stdu    25,8(3)         # offset 120
71         stdu    26,8(3)         # offset 128
72         stdu    27,8(3)         # offset 136
73         stdu    28,8(3)         # offset 144
74         stdu    29,8(3)         # offset 152
75         stdu    30,8(3)         # offset 160
76         stdu    31,8(3)         # offset 168
77         mflr    4
78         stdu    4,8(3)          # offset 176
79         mfcr    4
80         stwu    4,8(3)          # offset 184
81 #else
82         stw     1,0(3)          # offset 0
83         stwu    2,4(3)          # offset 4
84         stwu    13,4(3)         # offset 8
85         stwu    14,4(3)         # offset 12
86         stwu    15,4(3)         # offset 16
87         stwu    16,4(3)         # offset 20
88         stwu    17,4(3)         # offset 24
89         stwu    18,4(3)         # offset 28
90         stwu    19,4(3)         # offset 32
91         stwu    20,4(3)         # offset 36
92         stwu    21,4(3)         # offset 40
93         stwu    22,4(3)         # offset 44
94         stwu    23,4(3)         # offset 48
95         stwu    24,4(3)         # offset 52
96         stwu    25,4(3)         # offset 56
97         stwu    26,4(3)         # offset 60
98         stwu    27,4(3)         # offset 64
99         stwu    28,4(3)         # offset 68
100         stwu    29,4(3)         # offset 72
101         stwu    30,4(3)         # offset 76
102         stwu    31,4(3)         # offset 80
103 #endif
105 #if !__powerpc64__
106         /* If __SPE__, then add 84 to the offset shown from this point on until
107            the end of this function.  This difference comes from the fact that
108            we save 21 64-bit registers instead of 21 32-bit registers above.  */
109         mflr    4
110         stwu    4,4(3)          # offset 84
111         mfcr    4
112         stwu    4,4(3)          # offset 88
113                                 # one word pad to get floating point aligned on 8 byte boundary
114 #endif
116         /* Check whether we need to save FPRs.  Checking __NO_FPRS__
117            on its own would be enough for GCC 4.1 and above, but older
118            compilers only define _SOFT_FLOAT, so check both.  */
119 #if !defined (__NO_FPRS__) && !defined (_SOFT_FLOAT)
120 #if defined (__rtems__) && !defined (__PPC_CPU_E6500__)
121         /* For some RTEMS multilibs, the FPU and Altivec units are disabled
122            during interrupt handling.  Do not save and restore the
123            corresponding registers in this case.  */
124         mfmsr   5
125         andi.   5,5,0x2000
126         beq     1f
127 #endif
129         /* If __powerpc64__, then add 96 to the offset shown from this point on until
130            the end of this function.  This difference comes from the fact that
131            we save 23 64-bit registers instead of 23 32-bit registers above and
132            we take alignement requirements of floating point and Altivec stores
133            into account.  */
135         stfdu   14,8(3)         # offset 96
136         stfdu   15,8(3)         # offset 104
137         stfdu   16,8(3)         # offset 112
138         stfdu   17,8(3)         # offset 120
139         stfdu   18,8(3)         # offset 128
140         stfdu   19,8(3)         # offset 136
141         stfdu   20,8(3)         # offset 144
142         stfdu   21,8(3)         # offset 152
143         stfdu   22,8(3)         # offset 160
144         stfdu   23,8(3)         # offset 168
145         stfdu   24,8(3)         # offset 176
146         stfdu   25,8(3)         # offset 184
147         stfdu   26,8(3)         # offset 192
148         stfdu   27,8(3)         # offset 200
149         stfdu   28,8(3)         # offset 208
150         stfdu   29,8(3)         # offset 216
151         stfdu   30,8(3)         # offset 224
152         stfdu   31,8(3)         # offset 232
154 #endif
156         /* This requires a total of 21 * 4 + 18 * 8 + 4 + 4 + 4
157            bytes == 60 * 4 bytes == 240 bytes.  */
159 #ifdef __ALTIVEC__
160 #if defined (__rtems__) && !defined (__PPC_CPU_E6500__)
161         mfmsr   5
162         andis.  5,5,0x200
163         beq     1f
164 #endif
165         /* save Altivec vrsave and vr20-vr31 registers */
166         mfspr   4,256           # vrsave register
167         stwu    4,16(3)         # offset 248
168         addi    3,3,8
169         stvx    20,0,3          # offset 256
170         addi    3,3,16
171         stvx    21,0,3          # offset 272
172         addi    3,3,16
173         stvx    22,0,3          # offset 288
174         addi    3,3,16
175         stvx    23,0,3          # offset 304
176         addi    3,3,16
177         stvx    24,0,3          # offset 320
178         addi    3,3,16
179         stvx    25,0,3          # offset 336
180         addi    3,3,16
181         stvx    26,0,3          # offset 352
182         addi    3,3,16
183         stvx    27,0,3          # offset 368
184         addi    3,3,16
185         stvx    28,0,3          # offset 384
186         addi    3,3,16
187         stvx    29,0,3          # offset 400
188         addi    3,3,16
189         stvx    30,0,3          # offset 416
190         addi    3,3,16
191         stvx    31,0,3          # offset 432
194         /* This requires a total of 240 + 8 + 8 + 12 * 16 == 448 bytes. */
195 #endif
196         li      3,0
197         blr
198 FUNC_END(setjmp)
201 FUNC_START(longjmp)
202 #ifdef __ALTIVEC__
203         addi    3,3,15          # align Altivec to 16 byte boundary
204 #if __powerpc64__
205         clrrdi  3,3,4
206 #else
207         rlwinm  3,3,0,0,27
208 #endif
209 #else
210         addi    3,3,7           # align to 8 byte boundary
211 #if __powerpc64__
212         clrrdi  3,3,3
213 #else
214         rlwinm  3,3,0,0,28
215 #endif
216 #endif
217 #if __SPE__
218         /* If we are E500, then restore 64-bit registers.  */
219         evldd   1,0(3)          # offset 0
220         evldd   2,8(3)          # offset 8
221         evldd   13,16(3)        # offset 16
222         evldd   14,24(3)        # offset 24
223         evldd   15,32(3)        # offset 32
224         evldd   16,40(3)        # offset 40
225         evldd   17,48(3)        # offset 48
226         evldd   18,56(3)        # offset 56
227         evldd   19,64(3)        # offset 64
228         evldd   20,72(3)        # offset 72
229         evldd   21,80(3)        # offset 80
230         evldd   22,88(3)        # offset 88
231         evldd   23,96(3)        # offset 96
232         evldd   24,104(3)       # offset 104
233         evldd   25,112(3)       # offset 112
234         evldd   26,120(3)       # offset 120
235         evldd   27,128(3)       # offset 128
236         evldd   28,136(3)       # offset 136
237         evldd   29,144(3)       # offset 144
238         evldd   30,152(3)       # offset 152
239         evldd   31,160(3)       # offset 160
241         /* Add 164 to r3 to account for the amount of data we just
242            loaded.  Note that we are not adding 168 because the next
243            load instruction uses an offset of 4.  */
244         addi    3,3,164
245 #elif __powerpc64__
246         /* In the first load, add 8 to r3 so that the subsequent floating
247            point loades are aligned on an 8 byte boundary and the Altivec
248            loads are aligned on a 16 byte boundary.  */
249         ldu     1,8(3)          # offset 8
250         ldu     2,8(3)          # offset 16
251         ldu     13,8(3)         # offset 24
252         ldu     14,8(3)         # offset 32
253         ldu     15,8(3)         # offset 40
254         ldu     16,8(3)         # offset 48
255         ldu     17,8(3)         # offset 56
256         ldu     18,8(3)         # offset 64
257         ldu     19,8(3)         # offset 72
258         ldu     20,8(3)         # offset 80
259         ldu     21,8(3)         # offset 88
260         ldu     22,8(3)         # offset 96
261         ldu     23,8(3)         # offset 104
262         ldu     24,8(3)         # offset 112
263         ldu     25,8(3)         # offset 120
264         ldu     26,8(3)         # offset 128
265         ldu     27,8(3)         # offset 136
266         ldu     28,8(3)         # offset 144
267         ldu     29,8(3)         # offset 152
268         ldu     30,8(3)         # offset 160
269         ldu     31,8(3)         # offset 168
270         ldu     5,8(3)          # offset 176
271         mtlr    5
272         lwzu    5,8(3)          # offset 184
273         mtcrf   255,5
274 #else
275         lwz     1,0(3)          # offset 0 
276         lwzu    2,4(3)          # offset 4 
277         lwzu    13,4(3)         # offset 8 
278         lwzu    14,4(3)         # offset 12
279         lwzu    15,4(3)         # offset 16
280         lwzu    16,4(3)         # offset 20
281         lwzu    17,4(3)         # offset 24
282         lwzu    18,4(3)         # offset 28
283         lwzu    19,4(3)         # offset 32
284         lwzu    20,4(3)         # offset 36
285         lwzu    21,4(3)         # offset 40
286         lwzu    22,4(3)         # offset 44
287         lwzu    23,4(3)         # offset 48
288         lwzu    24,4(3)         # offset 52
289         lwzu    25,4(3)         # offset 56
290         lwzu    26,4(3)         # offset 60
291         lwzu    27,4(3)         # offset 64
292         lwzu    28,4(3)         # offset 68
293         lwzu    29,4(3)         # offset 72
294         lwzu    30,4(3)         # offset 76
295         lwzu    31,4(3)         # offset 80
296 #endif
297         /* If __SPE__, then add 84 to the offset shown from this point on until
298            the end of this function.  This difference comes from the fact that
299            we restore 22 64-bit registers instead of 22 32-bit registers above.  */
301 #if !__powerpc64__
302         lwzu    5,4(3)          # offset 84
303         mtlr    5
304         lwzu    5,4(3)          # offset 88
305         mtcrf   255,5
306                                 # one word pad to get floating point aligned on 8 byte boundary
307 #endif
309         /* Check whether we need to restore FPRs.  Checking
310            __NO_FPRS__ on its own would be enough for GCC 4.1 and
311            above, but older compilers only define _SOFT_FLOAT, so
312            check both.  */
313 #if !defined (__NO_FPRS__) && !defined (_SOFT_FLOAT)
314 #if defined (__rtems__) && !defined (__PPC_CPU_E6500__)
315         mfmsr   5
316         andi.   5,5,0x2000
317         beq     1f
318 #endif
320         /* If __powerpc64__, then add 96 to the offset shown from this point on until
321            the end of this function.  This difference comes from the fact that
322            we restore 23 64-bit registers instead of 23 32-bit registers above and
323            we take alignement requirements of floating point and Altivec loads
324            into account.  */
326         lfdu    14,8(3)         # offset 96 
327         lfdu    15,8(3)         # offset 104
328         lfdu    16,8(3)         # offset 112
329         lfdu    17,8(3)         # offset 120
330         lfdu    18,8(3)         # offset 128
331         lfdu    19,8(3)         # offset 136
332         lfdu    20,8(3)         # offset 144
333         lfdu    21,8(3)         # offset 152
334         lfdu    22,8(3)         # offset 160
335         lfdu    23,8(3)         # offset 168
336         lfdu    24,8(3)         # offset 176
337         lfdu    25,8(3)         # offset 184
338         lfdu    26,8(3)         # offset 192
339         lfdu    27,8(3)         # offset 200
340         lfdu    28,8(3)         # offset 208
341         lfdu    29,8(3)         # offset 216
342         lfdu    30,8(3)         # offset 224
343         lfdu    31,8(3)         # offset 232
345 #endif
347 #ifdef __ALTIVEC__
348 #if defined (__rtems__) && !defined (__PPC_CPU_E6500__)
349         mfmsr   5
350         andis.  5,5,0x200
351         beq     1f
352 #endif
353         /* restore Altivec vrsave and v20-v31 registers */
354         lwzu    5,16(3)         # offset 248
355         mtspr   256,5           # vrsave
356         addi    3,3,8
357         lvx     20,0,3          # offset 256
358         addi    3,3,16
359         lvx     21,0,3          # offset 272
360         addi    3,3,16
361         lvx     22,0,3          # offset 288
362         addi    3,3,16
363         lvx     23,0,3          # offset 304
364         addi    3,3,16
365         lvx     24,0,3          # offset 320
366         addi    3,3,16
367         lvx     25,0,3          # offset 336
368         addi    3,3,16
369         lvx     26,0,3          # offset 352
370         addi    3,3,16
371         lvx     27,0,3          # offset 368
372         addi    3,3,16
373         lvx     28,0,3          # offset 384
374         addi    3,3,16
375         lvx     29,0,3          # offset 400
376         addi    3,3,16
377         lvx     30,0,3          # offset 416
378         addi    3,3,16
379         lvx     31,0,3          # offset 432
381 #endif
383         mr.     3,4
384         bclr+   4,2
385         li      3,1
386         blr
387 FUNC_END(longjmp)