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. */
10 addi 3,3,15 # align Altivec to 16 byte boundary
17 addi 3,3,7 # align to 8 byte boundary
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. */
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
78 stdu 4,8(3) # offset 176
80 stwu 4,8(3) # offset 184
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
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. */
110 stwu 4,4(3) # offset 84
112 stwu 4,4(3) # offset 88
113 # one word pad to get floating point aligned on 8 byte boundary
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. */
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
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
156 /* This requires a total of 21 * 4 + 18 * 8 + 4 + 4 + 4
157 bytes == 60 * 4 bytes == 240 bytes. */
160 #if defined (__rtems__) && !defined (__PPC_CPU_E6500__)
165 /* save Altivec vrsave and vr20-vr31 registers */
166 mfspr 4,256 # vrsave register
167 stwu 4,16(3) # offset 248
169 stvx 20,0,3 # offset 256
171 stvx 21,0,3 # offset 272
173 stvx 22,0,3 # offset 288
175 stvx 23,0,3 # offset 304
177 stvx 24,0,3 # offset 320
179 stvx 25,0,3 # offset 336
181 stvx 26,0,3 # offset 352
183 stvx 27,0,3 # offset 368
185 stvx 28,0,3 # offset 384
187 stvx 29,0,3 # offset 400
189 stvx 30,0,3 # offset 416
191 stvx 31,0,3 # offset 432
194 /* This requires a total of 240 + 8 + 8 + 12 * 16 == 448 bytes. */
203 addi 3,3,15 # align Altivec to 16 byte boundary
210 addi 3,3,7 # align to 8 byte boundary
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. */
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
272 lwzu 5,8(3) # offset 184
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
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. */
302 lwzu 5,4(3) # offset 84
304 lwzu 5,4(3) # offset 88
306 # one word pad to get floating point aligned on 8 byte boundary
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
313 #if !defined (__NO_FPRS__) && !defined (_SOFT_FLOAT)
314 #if defined (__rtems__) && !defined (__PPC_CPU_E6500__)
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
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
348 #if defined (__rtems__) && !defined (__PPC_CPU_E6500__)
353 /* restore Altivec vrsave and v20-v31 registers */
354 lwzu 5,16(3) # offset 248
357 lvx 20,0,3 # offset 256
359 lvx 21,0,3 # offset 272
361 lvx 22,0,3 # offset 288
363 lvx 23,0,3 # offset 304
365 lvx 24,0,3 # offset 320
367 lvx 25,0,3 # offset 336
369 lvx 26,0,3 # offset 352
371 lvx 27,0,3 # offset 368
373 lvx 28,0,3 # offset 384
375 lvx 29,0,3 # offset 400
377 lvx 30,0,3 # offset 416
379 lvx 31,0,3 # offset 432