1 | //===----------------------------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "assembly.h" |
10 | |
11 | #define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 |
12 | #define FROM_16_TO_31 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 |
13 | |
14 | #define FROM_0_TO_31 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 |
15 | #define FROM_32_TO_63 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63 |
16 | |
17 | #if defined(_AIX) |
18 | .toc |
19 | #else |
20 | .text |
21 | #endif |
22 | |
23 | #if !defined(__USING_SJLJ_EXCEPTIONS__) |
24 | |
25 | #if defined(__i386__) |
26 | DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto) |
27 | # |
28 | # extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *); |
29 | # |
30 | # On entry: |
31 | # + + |
32 | # +-----------------------+ |
33 | # + thread_state pointer + |
34 | # +-----------------------+ |
35 | # + return address + |
36 | # +-----------------------+ <-- SP |
37 | # + + |
38 | |
39 | _LIBUNWIND_CET_ENDBR |
40 | movl 4(%esp), %eax |
41 | # set up eax and ret on new stack location |
42 | movl 28(%eax), %edx # edx holds new stack pointer |
43 | subl $8,%edx |
44 | movl %edx, 28(%eax) |
45 | movl 0(%eax), %ebx |
46 | movl %ebx, 0(%edx) |
47 | movl 40(%eax), %ebx |
48 | movl %ebx, 4(%edx) |
49 | # we now have ret and eax pushed onto where new stack will be |
50 | # restore all registers |
51 | movl 4(%eax), %ebx |
52 | movl 8(%eax), %ecx |
53 | movl 12(%eax), %edx |
54 | movl 16(%eax), %edi |
55 | movl 20(%eax), %esi |
56 | movl 24(%eax), %ebp |
57 | movl 28(%eax), %esp |
58 | # skip ss |
59 | # skip eflags |
60 | pop %eax # eax was already pushed on new stack |
61 | pop %ecx |
62 | jmp *%ecx |
63 | # skip cs |
64 | # skip ds |
65 | # skip es |
66 | # skip fs |
67 | # skip gs |
68 | |
69 | #elif defined(__x86_64__) |
70 | |
71 | DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_64_jumpto) |
72 | # |
73 | # extern "C" void __libunwind_Registers_x86_64_jumpto(Registers_x86_64 *); |
74 | # |
75 | #if defined(_WIN64) |
76 | # On entry, thread_state pointer is in rcx; move it into rdi |
77 | # to share restore code below. Since this routine restores and |
78 | # overwrites all registers, we can use the same registers for |
79 | # pointers and temporaries as on unix even though win64 normally |
80 | # mustn't clobber some of them. |
81 | movq %rcx, %rdi |
82 | #else |
83 | # On entry, thread_state pointer is in rdi |
84 | #endif |
85 | |
86 | _LIBUNWIND_CET_ENDBR |
87 | movq 56(%rdi), %rax # rax holds new stack pointer |
88 | subq $16, %rax |
89 | movq %rax, 56(%rdi) |
90 | movq 32(%rdi), %rbx # store new rdi on new stack |
91 | movq %rbx, 0(%rax) |
92 | movq 128(%rdi), %rbx # store new rip on new stack |
93 | movq %rbx, 8(%rax) |
94 | # restore all registers |
95 | movq 0(%rdi), %rax |
96 | movq 8(%rdi), %rbx |
97 | movq 16(%rdi), %rcx |
98 | movq 24(%rdi), %rdx |
99 | # restore rdi later |
100 | movq 40(%rdi), %rsi |
101 | movq 48(%rdi), %rbp |
102 | # restore rsp later |
103 | movq 64(%rdi), %r8 |
104 | movq 72(%rdi), %r9 |
105 | movq 80(%rdi), %r10 |
106 | movq 88(%rdi), %r11 |
107 | movq 96(%rdi), %r12 |
108 | movq 104(%rdi), %r13 |
109 | movq 112(%rdi), %r14 |
110 | movq 120(%rdi), %r15 |
111 | # skip rflags |
112 | # skip cs |
113 | # skip fs |
114 | # skip gs |
115 | |
116 | #if defined(_WIN64) |
117 | movdqu 176(%rdi),%xmm0 |
118 | movdqu 192(%rdi),%xmm1 |
119 | movdqu 208(%rdi),%xmm2 |
120 | movdqu 224(%rdi),%xmm3 |
121 | movdqu 240(%rdi),%xmm4 |
122 | movdqu 256(%rdi),%xmm5 |
123 | movdqu 272(%rdi),%xmm6 |
124 | movdqu 288(%rdi),%xmm7 |
125 | movdqu 304(%rdi),%xmm8 |
126 | movdqu 320(%rdi),%xmm9 |
127 | movdqu 336(%rdi),%xmm10 |
128 | movdqu 352(%rdi),%xmm11 |
129 | movdqu 368(%rdi),%xmm12 |
130 | movdqu 384(%rdi),%xmm13 |
131 | movdqu 400(%rdi),%xmm14 |
132 | movdqu 416(%rdi),%xmm15 |
133 | #endif |
134 | movq 56(%rdi), %rsp # cut back rsp to new location |
135 | pop %rdi # rdi was saved here earlier |
136 | pop %rcx |
137 | jmpq *%rcx |
138 | |
139 | |
140 | #elif defined(__powerpc64__) |
141 | |
142 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv) |
143 | // |
144 | // void libunwind::Registers_ppc64::jumpto() |
145 | // |
146 | // On entry: |
147 | // thread_state pointer is in r3 |
148 | // |
149 | |
150 | // load register (GPR) |
151 | #define PPC64_LR(n) \ |
152 | ld n, (8 * (n + 2))(3) |
153 | |
154 | // restore integral registers |
155 | // skip r0 for now |
156 | // skip r1 for now |
157 | PPC64_LR(2) |
158 | // skip r3 for now |
159 | // skip r4 for now |
160 | // skip r5 for now |
161 | PPC64_LR(6) |
162 | PPC64_LR(7) |
163 | PPC64_LR(8) |
164 | PPC64_LR(9) |
165 | PPC64_LR(10) |
166 | PPC64_LR(11) |
167 | PPC64_LR(12) |
168 | PPC64_LR(13) |
169 | PPC64_LR(14) |
170 | PPC64_LR(15) |
171 | PPC64_LR(16) |
172 | PPC64_LR(17) |
173 | PPC64_LR(18) |
174 | PPC64_LR(19) |
175 | PPC64_LR(20) |
176 | PPC64_LR(21) |
177 | PPC64_LR(22) |
178 | PPC64_LR(23) |
179 | PPC64_LR(24) |
180 | PPC64_LR(25) |
181 | PPC64_LR(26) |
182 | PPC64_LR(27) |
183 | PPC64_LR(28) |
184 | PPC64_LR(29) |
185 | PPC64_LR(30) |
186 | PPC64_LR(31) |
187 | |
188 | #if defined(__VSX__) |
189 | |
190 | // restore VS registers |
191 | // (note that this also restores floating point registers and V registers, |
192 | // because part of VS is mapped to these registers) |
193 | |
194 | addi 4, 3, PPC64_OFFS_FP |
195 | |
196 | // load VS register |
197 | #ifdef __LITTLE_ENDIAN__ |
198 | // For little-endian targets, we need a swap since lxvd2x will load the register |
199 | // in the incorrect doubleword order. |
200 | // FIXME: when supporting targets older than Power9 on LE is no longer required, |
201 | // this can be changed to simply `lxv n, (16 * n)(4)`. |
202 | #define PPC64_LVS(n) \ |
203 | lxvd2x n, 0, 4 ;\ |
204 | xxswapd n, n ;\ |
205 | addi 4, 4, 16 |
206 | #else |
207 | #define PPC64_LVS(n) \ |
208 | lxvd2x n, 0, 4 ;\ |
209 | addi 4, 4, 16 |
210 | #endif |
211 | |
212 | // restore the first 32 VS regs (and also all floating point regs) |
213 | PPC64_LVS(0) |
214 | PPC64_LVS(1) |
215 | PPC64_LVS(2) |
216 | PPC64_LVS(3) |
217 | PPC64_LVS(4) |
218 | PPC64_LVS(5) |
219 | PPC64_LVS(6) |
220 | PPC64_LVS(7) |
221 | PPC64_LVS(8) |
222 | PPC64_LVS(9) |
223 | PPC64_LVS(10) |
224 | PPC64_LVS(11) |
225 | PPC64_LVS(12) |
226 | PPC64_LVS(13) |
227 | PPC64_LVS(14) |
228 | PPC64_LVS(15) |
229 | PPC64_LVS(16) |
230 | PPC64_LVS(17) |
231 | PPC64_LVS(18) |
232 | PPC64_LVS(19) |
233 | PPC64_LVS(20) |
234 | PPC64_LVS(21) |
235 | PPC64_LVS(22) |
236 | PPC64_LVS(23) |
237 | PPC64_LVS(24) |
238 | PPC64_LVS(25) |
239 | PPC64_LVS(26) |
240 | PPC64_LVS(27) |
241 | PPC64_LVS(28) |
242 | PPC64_LVS(29) |
243 | PPC64_LVS(30) |
244 | PPC64_LVS(31) |
245 | |
246 | #ifdef __LITTLE_ENDIAN__ |
247 | #define PPC64_CLVS_RESTORE(n) \ |
248 | addi 4, 3, PPC64_OFFS_FP + n * 16 ;\ |
249 | lxvd2x n, 0, 4 ;\ |
250 | xxswapd n, n |
251 | #else |
252 | #define PPC64_CLVS_RESTORE(n) \ |
253 | addi 4, 3, PPC64_OFFS_FP + n * 16 ;\ |
254 | lxvd2x n, 0, 4 |
255 | #endif |
256 | |
257 | #if !defined(_AIX) |
258 | // use VRSAVE to conditionally restore the remaining VS regs, that are |
259 | // where the V regs are mapped. In the AIX ABI, VRSAVE is not used. |
260 | ld 5, PPC64_OFFS_VRSAVE(3) // test VRsave |
261 | cmpwi 5, 0 |
262 | beq Lnovec |
263 | |
264 | // conditionally load VS |
265 | #define PPC64_CLVSl(n) \ |
266 | andis. 0, 5, (1 PPC_LEFT_SHIFT(47-n)) ;\ |
267 | beq Ldone##n ;\ |
268 | PPC64_CLVS_RESTORE(n) ;\ |
269 | Ldone##n: |
270 | |
271 | #define PPC64_CLVSh(n) \ |
272 | andi. 0, 5, (1 PPC_LEFT_SHIFT(63-n)) ;\ |
273 | beq Ldone##n ;\ |
274 | PPC64_CLVS_RESTORE(n) ;\ |
275 | Ldone##n: |
276 | |
277 | #else |
278 | |
279 | #define PPC64_CLVSl(n) PPC64_CLVS_RESTORE(n) |
280 | #define PPC64_CLVSh(n) PPC64_CLVS_RESTORE(n) |
281 | |
282 | #endif // !defined(_AIX) |
283 | |
284 | PPC64_CLVSl(32) |
285 | PPC64_CLVSl(33) |
286 | PPC64_CLVSl(34) |
287 | PPC64_CLVSl(35) |
288 | PPC64_CLVSl(36) |
289 | PPC64_CLVSl(37) |
290 | PPC64_CLVSl(38) |
291 | PPC64_CLVSl(39) |
292 | PPC64_CLVSl(40) |
293 | PPC64_CLVSl(41) |
294 | PPC64_CLVSl(42) |
295 | PPC64_CLVSl(43) |
296 | PPC64_CLVSl(44) |
297 | PPC64_CLVSl(45) |
298 | PPC64_CLVSl(46) |
299 | PPC64_CLVSl(47) |
300 | PPC64_CLVSh(48) |
301 | PPC64_CLVSh(49) |
302 | PPC64_CLVSh(50) |
303 | PPC64_CLVSh(51) |
304 | PPC64_CLVSh(52) |
305 | PPC64_CLVSh(53) |
306 | PPC64_CLVSh(54) |
307 | PPC64_CLVSh(55) |
308 | PPC64_CLVSh(56) |
309 | PPC64_CLVSh(57) |
310 | PPC64_CLVSh(58) |
311 | PPC64_CLVSh(59) |
312 | PPC64_CLVSh(60) |
313 | PPC64_CLVSh(61) |
314 | PPC64_CLVSh(62) |
315 | PPC64_CLVSh(63) |
316 | |
317 | #else |
318 | |
319 | // load FP register |
320 | #define PPC64_LF(n) \ |
321 | lfd n, (PPC64_OFFS_FP + n * 16)(3) |
322 | |
323 | // restore float registers |
324 | PPC64_LF(0) |
325 | PPC64_LF(1) |
326 | PPC64_LF(2) |
327 | PPC64_LF(3) |
328 | PPC64_LF(4) |
329 | PPC64_LF(5) |
330 | PPC64_LF(6) |
331 | PPC64_LF(7) |
332 | PPC64_LF(8) |
333 | PPC64_LF(9) |
334 | PPC64_LF(10) |
335 | PPC64_LF(11) |
336 | PPC64_LF(12) |
337 | PPC64_LF(13) |
338 | PPC64_LF(14) |
339 | PPC64_LF(15) |
340 | PPC64_LF(16) |
341 | PPC64_LF(17) |
342 | PPC64_LF(18) |
343 | PPC64_LF(19) |
344 | PPC64_LF(20) |
345 | PPC64_LF(21) |
346 | PPC64_LF(22) |
347 | PPC64_LF(23) |
348 | PPC64_LF(24) |
349 | PPC64_LF(25) |
350 | PPC64_LF(26) |
351 | PPC64_LF(27) |
352 | PPC64_LF(28) |
353 | PPC64_LF(29) |
354 | PPC64_LF(30) |
355 | PPC64_LF(31) |
356 | |
357 | #if defined(__ALTIVEC__) |
358 | |
359 | #define PPC64_CLV_UNALIGNED_RESTORE(n) \ |
360 | ld 0, (PPC64_OFFS_V + n * 16)(3) ;\ |
361 | std 0, 0(4) ;\ |
362 | ld 0, (PPC64_OFFS_V + n * 16 + 8)(3) ;\ |
363 | std 0, 8(4) ;\ |
364 | lvx n, 0, 4 |
365 | |
366 | #if !defined(_AIX) |
367 | // restore vector registers if any are in use. In the AIX ABI, VRSAVE is |
368 | // not used. |
369 | ld 5, PPC64_OFFS_VRSAVE(3) // test VRsave |
370 | cmpwi 5, 0 |
371 | beq Lnovec |
372 | |
373 | #define PPC64_CLV_UNALIGNEDl(n) \ |
374 | andis. 0, 5, (1 PPC_LEFT_SHIFT(15-n)) ;\ |
375 | beq Ldone##n ;\ |
376 | PPC64_CLV_UNALIGNED_RESTORE(n) ;\ |
377 | Ldone ## n: |
378 | |
379 | #define PPC64_CLV_UNALIGNEDh(n) \ |
380 | andi. 0, 5, (1 PPC_LEFT_SHIFT(31-n)) ;\ |
381 | beq Ldone##n ;\ |
382 | PPC64_CLV_UNALIGNED_RESTORE(n) ;\ |
383 | Ldone ## n: |
384 | |
385 | #else |
386 | |
387 | #define PPC64_CLV_UNALIGNEDl(n) PPC64_CLV_UNALIGNED_RESTORE(n) |
388 | #define PPC64_CLV_UNALIGNEDh(n) PPC64_CLV_UNALIGNED_RESTORE(n) |
389 | |
390 | #endif // !defined(_AIX) |
391 | |
392 | subi 4, 1, 16 |
393 | // r4 is now a 16-byte aligned pointer into the red zone |
394 | // the _vectorScalarRegisters may not be 16-byte aligned |
395 | // so copy via red zone temp buffer |
396 | |
397 | PPC64_CLV_UNALIGNEDl(0) |
398 | PPC64_CLV_UNALIGNEDl(1) |
399 | PPC64_CLV_UNALIGNEDl(2) |
400 | PPC64_CLV_UNALIGNEDl(3) |
401 | PPC64_CLV_UNALIGNEDl(4) |
402 | PPC64_CLV_UNALIGNEDl(5) |
403 | PPC64_CLV_UNALIGNEDl(6) |
404 | PPC64_CLV_UNALIGNEDl(7) |
405 | PPC64_CLV_UNALIGNEDl(8) |
406 | PPC64_CLV_UNALIGNEDl(9) |
407 | PPC64_CLV_UNALIGNEDl(10) |
408 | PPC64_CLV_UNALIGNEDl(11) |
409 | PPC64_CLV_UNALIGNEDl(12) |
410 | PPC64_CLV_UNALIGNEDl(13) |
411 | PPC64_CLV_UNALIGNEDl(14) |
412 | PPC64_CLV_UNALIGNEDl(15) |
413 | PPC64_CLV_UNALIGNEDh(16) |
414 | PPC64_CLV_UNALIGNEDh(17) |
415 | PPC64_CLV_UNALIGNEDh(18) |
416 | PPC64_CLV_UNALIGNEDh(19) |
417 | PPC64_CLV_UNALIGNEDh(20) |
418 | PPC64_CLV_UNALIGNEDh(21) |
419 | PPC64_CLV_UNALIGNEDh(22) |
420 | PPC64_CLV_UNALIGNEDh(23) |
421 | PPC64_CLV_UNALIGNEDh(24) |
422 | PPC64_CLV_UNALIGNEDh(25) |
423 | PPC64_CLV_UNALIGNEDh(26) |
424 | PPC64_CLV_UNALIGNEDh(27) |
425 | PPC64_CLV_UNALIGNEDh(28) |
426 | PPC64_CLV_UNALIGNEDh(29) |
427 | PPC64_CLV_UNALIGNEDh(30) |
428 | PPC64_CLV_UNALIGNEDh(31) |
429 | |
430 | #endif |
431 | #endif |
432 | |
433 | Lnovec: |
434 | ld 0, PPC64_OFFS_CR(3) |
435 | mtcr 0 |
436 | ld 0, PPC64_OFFS_SRR0(3) |
437 | mtctr 0 |
438 | |
439 | #if defined(_AIX) |
440 | // After setting GPR1 to a higher address, AIX wipes out the original |
441 | // stack space below that address invalidated by the new GPR1 value. Use |
442 | // GPR0 to save the value of GPR3 in the context before it is wiped out. |
443 | // This compromises the content of GPR0 which is a volatile register. |
444 | ld 0, (8 * (3 + 2))(3) |
445 | #else |
446 | PPC64_LR(0) |
447 | #endif |
448 | PPC64_LR(5) |
449 | PPC64_LR(4) |
450 | PPC64_LR(1) |
451 | #if defined(_AIX) |
452 | mr 3, 0 |
453 | #else |
454 | PPC64_LR(3) |
455 | #endif |
456 | bctr |
457 | |
458 | #elif defined(__powerpc__) |
459 | |
460 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) |
461 | // |
462 | // void libunwind::Registers_ppc::jumpto() |
463 | // |
464 | // On entry: |
465 | // thread_state pointer is in r3 |
466 | // |
467 | |
468 | // restore integral registers |
469 | // skip r0 for now |
470 | // skip r1 for now |
471 | lwz 2, 16(3) |
472 | // skip r3 for now |
473 | // skip r4 for now |
474 | // skip r5 for now |
475 | lwz 6, 32(3) |
476 | lwz 7, 36(3) |
477 | lwz 8, 40(3) |
478 | lwz 9, 44(3) |
479 | lwz 10, 48(3) |
480 | lwz 11, 52(3) |
481 | lwz 12, 56(3) |
482 | lwz 13, 60(3) |
483 | lwz 14, 64(3) |
484 | lwz 15, 68(3) |
485 | lwz 16, 72(3) |
486 | lwz 17, 76(3) |
487 | lwz 18, 80(3) |
488 | lwz 19, 84(3) |
489 | lwz 20, 88(3) |
490 | lwz 21, 92(3) |
491 | lwz 22, 96(3) |
492 | lwz 23,100(3) |
493 | lwz 24,104(3) |
494 | lwz 25,108(3) |
495 | lwz 26,112(3) |
496 | lwz 27,116(3) |
497 | lwz 28,120(3) |
498 | lwz 29,124(3) |
499 | lwz 30,128(3) |
500 | lwz 31,132(3) |
501 | |
502 | #ifndef __NO_FPRS__ |
503 | // restore float registers |
504 | lfd 0, 160(3) |
505 | lfd 1, 168(3) |
506 | lfd 2, 176(3) |
507 | lfd 3, 184(3) |
508 | lfd 4, 192(3) |
509 | lfd 5, 200(3) |
510 | lfd 6, 208(3) |
511 | lfd 7, 216(3) |
512 | lfd 8, 224(3) |
513 | lfd 9, 232(3) |
514 | lfd 10,240(3) |
515 | lfd 11,248(3) |
516 | lfd 12,256(3) |
517 | lfd 13,264(3) |
518 | lfd 14,272(3) |
519 | lfd 15,280(3) |
520 | lfd 16,288(3) |
521 | lfd 17,296(3) |
522 | lfd 18,304(3) |
523 | lfd 19,312(3) |
524 | lfd 20,320(3) |
525 | lfd 21,328(3) |
526 | lfd 22,336(3) |
527 | lfd 23,344(3) |
528 | lfd 24,352(3) |
529 | lfd 25,360(3) |
530 | lfd 26,368(3) |
531 | lfd 27,376(3) |
532 | lfd 28,384(3) |
533 | lfd 29,392(3) |
534 | lfd 30,400(3) |
535 | lfd 31,408(3) |
536 | #endif |
537 | |
538 | #if defined(__ALTIVEC__) |
539 | |
540 | #define LOAD_VECTOR_RESTORE(_index) \ |
541 | lwz 0, 424+_index*16(3) SEPARATOR \ |
542 | stw 0, 0(4) SEPARATOR \ |
543 | lwz 0, 424+_index*16+4(3) SEPARATOR \ |
544 | stw 0, 4(4) SEPARATOR \ |
545 | lwz 0, 424+_index*16+8(3) SEPARATOR \ |
546 | stw 0, 8(4) SEPARATOR \ |
547 | lwz 0, 424+_index*16+12(3) SEPARATOR \ |
548 | stw 0, 12(4) SEPARATOR \ |
549 | lvx _index, 0, 4 |
550 | |
551 | #if !defined(_AIX) |
552 | // restore vector registers if any are in use. In the AIX ABI, VRSAVE |
553 | // is not used. |
554 | lwz 5, 156(3) // test VRsave |
555 | cmpwi 5, 0 |
556 | beq Lnovec |
557 | |
558 | #define LOAD_VECTOR_UNALIGNEDl(_index) \ |
559 | andis. 0, 5, (1 PPC_LEFT_SHIFT(15-_index)) SEPARATOR \ |
560 | beq Ldone ## _index SEPARATOR \ |
561 | LOAD_VECTOR_RESTORE(_index) SEPARATOR \ |
562 | Ldone ## _index: |
563 | |
564 | #define LOAD_VECTOR_UNALIGNEDh(_index) \ |
565 | andi. 0, 5, (1 PPC_LEFT_SHIFT(31-_index)) SEPARATOR \ |
566 | beq Ldone ## _index SEPARATOR \ |
567 | LOAD_VECTOR_RESTORE(_index) SEPARATOR \ |
568 | Ldone ## _index: |
569 | |
570 | #else |
571 | |
572 | #define LOAD_VECTOR_UNALIGNEDl(_index) LOAD_VECTOR_RESTORE(_index) |
573 | #define LOAD_VECTOR_UNALIGNEDh(_index) LOAD_VECTOR_RESTORE(_index) |
574 | |
575 | #endif // !defined(_AIX) |
576 | |
577 | subi 4, 1, 16 |
578 | rlwinm 4, 4, 0, 0, 27 // mask low 4-bits |
579 | // r4 is now a 16-byte aligned pointer into the red zone |
580 | // the _vectorRegisters may not be 16-byte aligned so copy via red zone temp buffer |
581 | |
582 | LOAD_VECTOR_UNALIGNEDl(0) |
583 | LOAD_VECTOR_UNALIGNEDl(1) |
584 | LOAD_VECTOR_UNALIGNEDl(2) |
585 | LOAD_VECTOR_UNALIGNEDl(3) |
586 | LOAD_VECTOR_UNALIGNEDl(4) |
587 | LOAD_VECTOR_UNALIGNEDl(5) |
588 | LOAD_VECTOR_UNALIGNEDl(6) |
589 | LOAD_VECTOR_UNALIGNEDl(7) |
590 | LOAD_VECTOR_UNALIGNEDl(8) |
591 | LOAD_VECTOR_UNALIGNEDl(9) |
592 | LOAD_VECTOR_UNALIGNEDl(10) |
593 | LOAD_VECTOR_UNALIGNEDl(11) |
594 | LOAD_VECTOR_UNALIGNEDl(12) |
595 | LOAD_VECTOR_UNALIGNEDl(13) |
596 | LOAD_VECTOR_UNALIGNEDl(14) |
597 | LOAD_VECTOR_UNALIGNEDl(15) |
598 | LOAD_VECTOR_UNALIGNEDh(16) |
599 | LOAD_VECTOR_UNALIGNEDh(17) |
600 | LOAD_VECTOR_UNALIGNEDh(18) |
601 | LOAD_VECTOR_UNALIGNEDh(19) |
602 | LOAD_VECTOR_UNALIGNEDh(20) |
603 | LOAD_VECTOR_UNALIGNEDh(21) |
604 | LOAD_VECTOR_UNALIGNEDh(22) |
605 | LOAD_VECTOR_UNALIGNEDh(23) |
606 | LOAD_VECTOR_UNALIGNEDh(24) |
607 | LOAD_VECTOR_UNALIGNEDh(25) |
608 | LOAD_VECTOR_UNALIGNEDh(26) |
609 | LOAD_VECTOR_UNALIGNEDh(27) |
610 | LOAD_VECTOR_UNALIGNEDh(28) |
611 | LOAD_VECTOR_UNALIGNEDh(29) |
612 | LOAD_VECTOR_UNALIGNEDh(30) |
613 | LOAD_VECTOR_UNALIGNEDh(31) |
614 | #endif |
615 | |
616 | Lnovec: |
617 | lwz 0, 136(3) // __cr |
618 | mtcr 0 |
619 | lwz 0, 148(3) // __ctr |
620 | mtctr 0 |
621 | lwz 0, 0(3) // __ssr0 |
622 | mtctr 0 |
623 | lwz 0, 8(3) // do r0 now |
624 | lwz 5, 28(3) // do r5 now |
625 | lwz 4, 24(3) // do r4 now |
626 | lwz 1, 12(3) // do sp now |
627 | lwz 3, 20(3) // do r3 last |
628 | bctr |
629 | |
630 | #elif defined(__aarch64__) |
631 | |
632 | // |
633 | // extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *); |
634 | // |
635 | // On entry: |
636 | // thread_state pointer is in x0 |
637 | // |
638 | .p2align 2 |
639 | DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto) |
640 | // skip restore of x0,x1 for now |
641 | ldp x2, x3, [x0, #0x010] |
642 | ldp x4, x5, [x0, #0x020] |
643 | ldp x6, x7, [x0, #0x030] |
644 | ldp x8, x9, [x0, #0x040] |
645 | ldp x10,x11, [x0, #0x050] |
646 | ldp x12,x13, [x0, #0x060] |
647 | ldp x14,x15, [x0, #0x070] |
648 | // x16 and x17 were clobbered by the call into the unwinder, so no point in |
649 | // restoring them. |
650 | ldp x18,x19, [x0, #0x090] |
651 | ldp x20,x21, [x0, #0x0A0] |
652 | ldp x22,x23, [x0, #0x0B0] |
653 | ldp x24,x25, [x0, #0x0C0] |
654 | ldp x26,x27, [x0, #0x0D0] |
655 | ldp x28,x29, [x0, #0x0E0] |
656 | ldr x30, [x0, #0x100] // restore pc into lr |
657 | |
658 | ldp d0, d1, [x0, #0x110] |
659 | ldp d2, d3, [x0, #0x120] |
660 | ldp d4, d5, [x0, #0x130] |
661 | ldp d6, d7, [x0, #0x140] |
662 | ldp d8, d9, [x0, #0x150] |
663 | ldp d10,d11, [x0, #0x160] |
664 | ldp d12,d13, [x0, #0x170] |
665 | ldp d14,d15, [x0, #0x180] |
666 | ldp d16,d17, [x0, #0x190] |
667 | ldp d18,d19, [x0, #0x1A0] |
668 | ldp d20,d21, [x0, #0x1B0] |
669 | ldp d22,d23, [x0, #0x1C0] |
670 | ldp d24,d25, [x0, #0x1D0] |
671 | ldp d26,d27, [x0, #0x1E0] |
672 | ldp d28,d29, [x0, #0x1F0] |
673 | ldr d30, [x0, #0x200] |
674 | ldr d31, [x0, #0x208] |
675 | |
676 | // Finally, restore sp. This must be done after the last read from the |
677 | // context struct, because it is allocated on the stack, and an exception |
678 | // could clobber the de-allocated portion of the stack after sp has been |
679 | // restored. |
680 | ldr x16, [x0, #0x0F8] |
681 | ldp x0, x1, [x0, #0x000] // restore x0,x1 |
682 | mov sp,x16 // restore sp |
683 | ret x30 // jump to pc |
684 | |
685 | #elif defined(__arm__) && !defined(__APPLE__) |
686 | |
687 | #if !defined(__ARM_ARCH_ISA_ARM) |
688 | #if (__ARM_ARCH_ISA_THUMB == 2) |
689 | .syntax unified |
690 | #endif |
691 | .thumb |
692 | #endif |
693 | |
694 | @ |
695 | @ void libunwind::Registers_arm::restoreCoreAndJumpTo() |
696 | @ |
697 | @ On entry: |
698 | @ thread_state pointer is in r0 |
699 | @ |
700 | .p2align 2 |
701 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm20restoreCoreAndJumpToEv) |
702 | #if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1 |
703 | @ r8-r11: ldm into r1-r4, then mov to r8-r11 |
704 | adds r0, #0x20 |
705 | ldm r0!, {r1-r4} |
706 | subs r0, #0x30 |
707 | mov r8, r1 |
708 | mov r9, r2 |
709 | mov r10, r3 |
710 | mov r11, r4 |
711 | @ r12 does not need loading, it it the intra-procedure-call scratch register |
712 | ldr r2, [r0, #0x34] |
713 | ldr r3, [r0, #0x3c] |
714 | mov sp, r2 |
715 | mov lr, r3 @ restore pc into lr |
716 | ldm r0, {r0-r7} |
717 | #else |
718 | @ Use lr as base so that r0 can be restored. |
719 | mov lr, r0 |
720 | @ 32bit thumb-2 restrictions for ldm: |
721 | @ . the sp (r13) cannot be in the list |
722 | @ . the pc (r15) and lr (r14) cannot both be in the list in an LDM instruction |
723 | ldm lr, {r0-r12} |
724 | ldr sp, [lr, #52] |
725 | ldr lr, [lr, #60] @ restore pc into lr |
726 | #endif |
727 | #if defined(__ARM_FEATURE_BTI_DEFAULT) && !defined(__ARM_ARCH_ISA_ARM) |
728 | // 'bx' is not BTI setting when used with lr, therefore r12 is used instead |
729 | mov r12, lr |
730 | JMP(r12) |
731 | #else |
732 | JMP(lr) |
733 | #endif |
734 | |
735 | @ |
736 | @ static void libunwind::Registers_arm::restoreVFPWithFLDMD(unw_fpreg_t* values) |
737 | @ |
738 | @ On entry: |
739 | @ values pointer is in r0 |
740 | @ |
741 | .p2align 2 |
742 | #if defined(__ELF__) |
743 | .fpu vfpv3-d16 |
744 | #endif |
745 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMDEPv) |
746 | @ VFP and iwMMX instructions are only available when compiling with the flags |
747 | @ that enable them. We do not want to do that in the library (because we do not |
748 | @ want the compiler to generate instructions that access those) but this is |
749 | @ only accessed if the personality routine needs these registers. Use of |
750 | @ these registers implies they are, actually, available on the target, so |
751 | @ it's ok to execute. |
752 | @ So, generate the instruction using the corresponding coprocessor mnemonic. |
753 | vldmia r0, {d0-d15} |
754 | JMP(lr) |
755 | |
756 | @ |
757 | @ static void libunwind::Registers_arm::restoreVFPWithFLDMX(unw_fpreg_t* values) |
758 | @ |
759 | @ On entry: |
760 | @ values pointer is in r0 |
761 | @ |
762 | .p2align 2 |
763 | #if defined(__ELF__) |
764 | .fpu vfpv3-d16 |
765 | #endif |
766 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMXEPv) |
767 | vldmia r0, {d0-d15} @ fldmiax is deprecated in ARMv7+ and now behaves like vldmia |
768 | JMP(lr) |
769 | |
770 | @ |
771 | @ static void libunwind::Registers_arm::restoreVFPv3(unw_fpreg_t* values) |
772 | @ |
773 | @ On entry: |
774 | @ values pointer is in r0 |
775 | @ |
776 | .p2align 2 |
777 | #if defined(__ELF__) |
778 | .fpu vfpv3 |
779 | #endif |
780 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPv) |
781 | vldmia r0, {d16-d31} |
782 | JMP(lr) |
783 | |
784 | #if defined(__ARM_WMMX) |
785 | |
786 | @ |
787 | @ static void libunwind::Registers_arm::restoreiWMMX(unw_fpreg_t* values) |
788 | @ |
789 | @ On entry: |
790 | @ values pointer is in r0 |
791 | @ |
792 | .p2align 2 |
793 | #if defined(__ELF__) |
794 | .arch armv5te |
795 | #endif |
796 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPv) |
797 | ldcl p1, cr0, [r0], #8 @ wldrd wR0, [r0], #8 |
798 | ldcl p1, cr1, [r0], #8 @ wldrd wR1, [r0], #8 |
799 | ldcl p1, cr2, [r0], #8 @ wldrd wR2, [r0], #8 |
800 | ldcl p1, cr3, [r0], #8 @ wldrd wR3, [r0], #8 |
801 | ldcl p1, cr4, [r0], #8 @ wldrd wR4, [r0], #8 |
802 | ldcl p1, cr5, [r0], #8 @ wldrd wR5, [r0], #8 |
803 | ldcl p1, cr6, [r0], #8 @ wldrd wR6, [r0], #8 |
804 | ldcl p1, cr7, [r0], #8 @ wldrd wR7, [r0], #8 |
805 | ldcl p1, cr8, [r0], #8 @ wldrd wR8, [r0], #8 |
806 | ldcl p1, cr9, [r0], #8 @ wldrd wR9, [r0], #8 |
807 | ldcl p1, cr10, [r0], #8 @ wldrd wR10, [r0], #8 |
808 | ldcl p1, cr11, [r0], #8 @ wldrd wR11, [r0], #8 |
809 | ldcl p1, cr12, [r0], #8 @ wldrd wR12, [r0], #8 |
810 | ldcl p1, cr13, [r0], #8 @ wldrd wR13, [r0], #8 |
811 | ldcl p1, cr14, [r0], #8 @ wldrd wR14, [r0], #8 |
812 | ldcl p1, cr15, [r0], #8 @ wldrd wR15, [r0], #8 |
813 | JMP(lr) |
814 | |
815 | @ |
816 | @ static void libunwind::Registers_arm::restoreiWMMXControl(unw_uint32_t* values) |
817 | @ |
818 | @ On entry: |
819 | @ values pointer is in r0 |
820 | @ |
821 | .p2align 2 |
822 | #if defined(__ELF__) |
823 | .arch armv5te |
824 | #endif |
825 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm19restoreiWMMXControlEPj) |
826 | ldc2 p1, cr8, [r0], #4 @ wldrw wCGR0, [r0], #4 |
827 | ldc2 p1, cr9, [r0], #4 @ wldrw wCGR1, [r0], #4 |
828 | ldc2 p1, cr10, [r0], #4 @ wldrw wCGR2, [r0], #4 |
829 | ldc2 p1, cr11, [r0], #4 @ wldrw wCGR3, [r0], #4 |
830 | JMP(lr) |
831 | |
832 | #endif |
833 | |
834 | #elif defined(__or1k__) |
835 | |
836 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv) |
837 | # |
838 | # void libunwind::Registers_or1k::jumpto() |
839 | # |
840 | # On entry: |
841 | # thread_state pointer is in r3 |
842 | # |
843 | |
844 | # restore integral registers |
845 | l.lwz r0, 0(r3) |
846 | l.lwz r1, 4(r3) |
847 | l.lwz r2, 8(r3) |
848 | # skip r3 for now |
849 | l.lwz r4, 16(r3) |
850 | l.lwz r5, 20(r3) |
851 | l.lwz r6, 24(r3) |
852 | l.lwz r7, 28(r3) |
853 | l.lwz r8, 32(r3) |
854 | # skip r9 |
855 | l.lwz r10, 40(r3) |
856 | l.lwz r11, 44(r3) |
857 | l.lwz r12, 48(r3) |
858 | l.lwz r13, 52(r3) |
859 | l.lwz r14, 56(r3) |
860 | l.lwz r15, 60(r3) |
861 | l.lwz r16, 64(r3) |
862 | l.lwz r17, 68(r3) |
863 | l.lwz r18, 72(r3) |
864 | l.lwz r19, 76(r3) |
865 | l.lwz r20, 80(r3) |
866 | l.lwz r21, 84(r3) |
867 | l.lwz r22, 88(r3) |
868 | l.lwz r23, 92(r3) |
869 | l.lwz r24, 96(r3) |
870 | l.lwz r25,100(r3) |
871 | l.lwz r26,104(r3) |
872 | l.lwz r27,108(r3) |
873 | l.lwz r28,112(r3) |
874 | l.lwz r29,116(r3) |
875 | l.lwz r30,120(r3) |
876 | l.lwz r31,124(r3) |
877 | |
878 | # load new pc into ra |
879 | l.lwz r9, 128(r3) |
880 | |
881 | # at last, restore r3 |
882 | l.lwz r3, 12(r3) |
883 | |
884 | # jump to pc |
885 | l.jr r9 |
886 | l.nop |
887 | |
888 | #elif defined(__hexagon__) |
889 | # On entry: |
890 | # thread_state pointer is in r2 |
891 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind17Registers_hexagon6jumptoEv) |
892 | # |
893 | # void libunwind::Registers_hexagon::jumpto() |
894 | # |
895 | r8 = memw(r0+#32) |
896 | r9 = memw(r0+#36) |
897 | r10 = memw(r0+#40) |
898 | r11 = memw(r0+#44) |
899 | |
900 | r12 = memw(r0+#48) |
901 | r13 = memw(r0+#52) |
902 | r14 = memw(r0+#56) |
903 | r15 = memw(r0+#60) |
904 | |
905 | r16 = memw(r0+#64) |
906 | r17 = memw(r0+#68) |
907 | r18 = memw(r0+#72) |
908 | r19 = memw(r0+#76) |
909 | |
910 | r20 = memw(r0+#80) |
911 | r21 = memw(r0+#84) |
912 | r22 = memw(r0+#88) |
913 | r23 = memw(r0+#92) |
914 | |
915 | r24 = memw(r0+#96) |
916 | r25 = memw(r0+#100) |
917 | r26 = memw(r0+#104) |
918 | r27 = memw(r0+#108) |
919 | |
920 | r28 = memw(r0+#112) |
921 | r29 = memw(r0+#116) |
922 | r30 = memw(r0+#120) |
923 | r31 = memw(r0+#132) |
924 | |
925 | r1 = memw(r0+#128) |
926 | c4 = r1 // Predicate register |
927 | r1 = memw(r0+#4) |
928 | r0 = memw(r0) |
929 | jumpr r31 |
930 | #elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 |
931 | |
932 | // |
933 | // void libunwind::Registers_mips_o32::jumpto() |
934 | // |
935 | // On entry: |
936 | // thread state pointer is in a0 ($4) |
937 | // |
938 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv) |
939 | .set push |
940 | .set noat |
941 | .set noreorder |
942 | .set nomacro |
943 | #ifdef __mips_hard_float |
944 | #if __mips_fpr != 64 |
945 | ldc1 $f0, (4 * 36 + 8 * 0)($4) |
946 | ldc1 $f2, (4 * 36 + 8 * 2)($4) |
947 | ldc1 $f4, (4 * 36 + 8 * 4)($4) |
948 | ldc1 $f6, (4 * 36 + 8 * 6)($4) |
949 | ldc1 $f8, (4 * 36 + 8 * 8)($4) |
950 | ldc1 $f10, (4 * 36 + 8 * 10)($4) |
951 | ldc1 $f12, (4 * 36 + 8 * 12)($4) |
952 | ldc1 $f14, (4 * 36 + 8 * 14)($4) |
953 | ldc1 $f16, (4 * 36 + 8 * 16)($4) |
954 | ldc1 $f18, (4 * 36 + 8 * 18)($4) |
955 | ldc1 $f20, (4 * 36 + 8 * 20)($4) |
956 | ldc1 $f22, (4 * 36 + 8 * 22)($4) |
957 | ldc1 $f24, (4 * 36 + 8 * 24)($4) |
958 | ldc1 $f26, (4 * 36 + 8 * 26)($4) |
959 | ldc1 $f28, (4 * 36 + 8 * 28)($4) |
960 | ldc1 $f30, (4 * 36 + 8 * 30)($4) |
961 | #else |
962 | ldc1 $f0, (4 * 36 + 8 * 0)($4) |
963 | ldc1 $f1, (4 * 36 + 8 * 1)($4) |
964 | ldc1 $f2, (4 * 36 + 8 * 2)($4) |
965 | ldc1 $f3, (4 * 36 + 8 * 3)($4) |
966 | ldc1 $f4, (4 * 36 + 8 * 4)($4) |
967 | ldc1 $f5, (4 * 36 + 8 * 5)($4) |
968 | ldc1 $f6, (4 * 36 + 8 * 6)($4) |
969 | ldc1 $f7, (4 * 36 + 8 * 7)($4) |
970 | ldc1 $f8, (4 * 36 + 8 * 8)($4) |
971 | ldc1 $f9, (4 * 36 + 8 * 9)($4) |
972 | ldc1 $f10, (4 * 36 + 8 * 10)($4) |
973 | ldc1 $f11, (4 * 36 + 8 * 11)($4) |
974 | ldc1 $f12, (4 * 36 + 8 * 12)($4) |
975 | ldc1 $f13, (4 * 36 + 8 * 13)($4) |
976 | ldc1 $f14, (4 * 36 + 8 * 14)($4) |
977 | ldc1 $f15, (4 * 36 + 8 * 15)($4) |
978 | ldc1 $f16, (4 * 36 + 8 * 16)($4) |
979 | ldc1 $f17, (4 * 36 + 8 * 17)($4) |
980 | ldc1 $f18, (4 * 36 + 8 * 18)($4) |
981 | ldc1 $f19, (4 * 36 + 8 * 19)($4) |
982 | ldc1 $f20, (4 * 36 + 8 * 20)($4) |
983 | ldc1 $f21, (4 * 36 + 8 * 21)($4) |
984 | ldc1 $f22, (4 * 36 + 8 * 22)($4) |
985 | ldc1 $f23, (4 * 36 + 8 * 23)($4) |
986 | ldc1 $f24, (4 * 36 + 8 * 24)($4) |
987 | ldc1 $f25, (4 * 36 + 8 * 25)($4) |
988 | ldc1 $f26, (4 * 36 + 8 * 26)($4) |
989 | ldc1 $f27, (4 * 36 + 8 * 27)($4) |
990 | ldc1 $f28, (4 * 36 + 8 * 28)($4) |
991 | ldc1 $f29, (4 * 36 + 8 * 29)($4) |
992 | ldc1 $f30, (4 * 36 + 8 * 30)($4) |
993 | ldc1 $f31, (4 * 36 + 8 * 31)($4) |
994 | #endif |
995 | #endif |
996 | #if __mips_isa_rev < 6 |
997 | // restore hi and lo |
998 | lw $8, (4 * 33)($4) |
999 | mthi $8 |
1000 | lw $8, (4 * 34)($4) |
1001 | mtlo $8 |
1002 | #endif |
1003 | // r0 is zero |
1004 | lw $1, (4 * 1)($4) |
1005 | lw $2, (4 * 2)($4) |
1006 | lw $3, (4 * 3)($4) |
1007 | // skip a0 for now |
1008 | lw $5, (4 * 5)($4) |
1009 | lw $6, (4 * 6)($4) |
1010 | lw $7, (4 * 7)($4) |
1011 | lw $8, (4 * 8)($4) |
1012 | lw $9, (4 * 9)($4) |
1013 | lw $10, (4 * 10)($4) |
1014 | lw $11, (4 * 11)($4) |
1015 | lw $12, (4 * 12)($4) |
1016 | lw $13, (4 * 13)($4) |
1017 | lw $14, (4 * 14)($4) |
1018 | lw $15, (4 * 15)($4) |
1019 | lw $16, (4 * 16)($4) |
1020 | lw $17, (4 * 17)($4) |
1021 | lw $18, (4 * 18)($4) |
1022 | lw $19, (4 * 19)($4) |
1023 | lw $20, (4 * 20)($4) |
1024 | lw $21, (4 * 21)($4) |
1025 | lw $22, (4 * 22)($4) |
1026 | lw $23, (4 * 23)($4) |
1027 | lw $24, (4 * 24)($4) |
1028 | lw $25, (4 * 25)($4) |
1029 | lw $26, (4 * 26)($4) |
1030 | lw $27, (4 * 27)($4) |
1031 | lw $28, (4 * 28)($4) |
1032 | lw $29, (4 * 29)($4) |
1033 | lw $30, (4 * 30)($4) |
1034 | // load new pc into ra |
1035 | lw $31, (4 * 32)($4) |
1036 | // jump to ra, load a0 in the delay slot |
1037 | jr $31 |
1038 | lw $4, (4 * 4)($4) |
1039 | .set pop |
1040 | |
1041 | #elif defined(__mips64) |
1042 | |
1043 | // |
1044 | // void libunwind::Registers_mips_newabi::jumpto() |
1045 | // |
1046 | // On entry: |
1047 | // thread state pointer is in a0 ($4) |
1048 | // |
1049 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv) |
1050 | .set push |
1051 | .set noat |
1052 | .set noreorder |
1053 | .set nomacro |
1054 | #ifdef __mips_hard_float |
1055 | .irp i,FROM_0_TO_31 |
1056 | ldc1 $f\i, (280+8*\i)($4) |
1057 | .endr |
1058 | #endif |
1059 | #if __mips_isa_rev < 6 |
1060 | // restore hi and lo |
1061 | ld $8, (8 * 33)($4) |
1062 | mthi $8 |
1063 | ld $8, (8 * 34)($4) |
1064 | mtlo $8 |
1065 | #endif |
1066 | // r0 is zero |
1067 | ld $1, (8 * 1)($4) |
1068 | ld $2, (8 * 2)($4) |
1069 | ld $3, (8 * 3)($4) |
1070 | // skip a0 for now |
1071 | .irp i,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30 |
1072 | ld $\i, (8 * \i)($4) |
1073 | .endr |
1074 | // load new pc into ra |
1075 | ld $31, (8 * 32)($4) |
1076 | // jump to ra, load a0 in the delay slot |
1077 | jr $31 |
1078 | ld $4, (8 * 4)($4) |
1079 | .set pop |
1080 | |
1081 | #elif defined(__sparc__) && defined(__arch64__) |
1082 | |
1083 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind17Registers_sparc646jumptoEv) |
1084 | // |
1085 | // void libunwind::Registers_sparc64::jumpto() |
1086 | // |
1087 | // On entry: |
1088 | // thread_state pointer is in %o0 |
1089 | // |
1090 | .register %g2, #scratch |
1091 | .register %g3, #scratch |
1092 | .register %g6, #scratch |
1093 | .register %g7, #scratch |
1094 | flushw |
1095 | ldx [%o0 + 0x08], %g1 |
1096 | ldx [%o0 + 0x10], %g2 |
1097 | ldx [%o0 + 0x18], %g3 |
1098 | ldx [%o0 + 0x20], %g4 |
1099 | ldx [%o0 + 0x28], %g5 |
1100 | ldx [%o0 + 0x30], %g6 |
1101 | ldx [%o0 + 0x38], %g7 |
1102 | ldx [%o0 + 0x48], %o1 |
1103 | ldx [%o0 + 0x50], %o2 |
1104 | ldx [%o0 + 0x58], %o3 |
1105 | ldx [%o0 + 0x60], %o4 |
1106 | ldx [%o0 + 0x68], %o5 |
1107 | ldx [%o0 + 0x70], %o6 |
1108 | ldx [%o0 + 0x78], %o7 |
1109 | ldx [%o0 + 0x80], %l0 |
1110 | ldx [%o0 + 0x88], %l1 |
1111 | ldx [%o0 + 0x90], %l2 |
1112 | ldx [%o0 + 0x98], %l3 |
1113 | ldx [%o0 + 0xa0], %l4 |
1114 | ldx [%o0 + 0xa8], %l5 |
1115 | ldx [%o0 + 0xb0], %l6 |
1116 | ldx [%o0 + 0xb8], %l7 |
1117 | ldx [%o0 + 0xc0], %i0 |
1118 | ldx [%o0 + 0xc8], %i1 |
1119 | ldx [%o0 + 0xd0], %i2 |
1120 | ldx [%o0 + 0xd8], %i3 |
1121 | ldx [%o0 + 0xe0], %i4 |
1122 | ldx [%o0 + 0xe8], %i5 |
1123 | ldx [%o0 + 0xf0], %i6 |
1124 | ldx [%o0 + 0xf8], %i7 |
1125 | jmp %o7 |
1126 | ldx [%o0 + 0x40], %o0 |
1127 | |
1128 | #elif defined(__sparc__) |
1129 | |
1130 | // |
1131 | // void libunwind::Registers_sparc_o32::jumpto() |
1132 | // |
1133 | // On entry: |
1134 | // thread_state pointer is in o0 |
1135 | // |
1136 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_sparc6jumptoEv) |
1137 | ta 3 |
1138 | ldd [%o0 + 64], %l0 |
1139 | ldd [%o0 + 72], %l2 |
1140 | ldd [%o0 + 80], %l4 |
1141 | ldd [%o0 + 88], %l6 |
1142 | ldd [%o0 + 96], %i0 |
1143 | ldd [%o0 + 104], %i2 |
1144 | ldd [%o0 + 112], %i4 |
1145 | ldd [%o0 + 120], %i6 |
1146 | ld [%o0 + 60], %o7 |
1147 | jmp %o7 |
1148 | nop |
1149 | |
1150 | #elif defined(__riscv) |
1151 | |
1152 | // |
1153 | // void libunwind::Registers_riscv::jumpto() |
1154 | // |
1155 | // On entry: |
1156 | // thread_state pointer is in a0 |
1157 | // |
1158 | .p2align 2 |
1159 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv) |
1160 | # if defined(__riscv_flen) |
1161 | .irp i,FROM_0_TO_31 |
1162 | FLOAD f\i, (RISCV_FOFFSET + RISCV_FSIZE * \i)(a0) |
1163 | .endr |
1164 | # endif |
1165 | |
1166 | // x0 is zero |
1167 | ILOAD x1, (RISCV_ISIZE * 0)(a0) // restore pc into ra |
1168 | .irp i,2,3,4,5,6,7,8,9 |
1169 | ILOAD x\i, (RISCV_ISIZE * \i)(a0) |
1170 | .endr |
1171 | // skip a0 for now |
1172 | .irp i,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 |
1173 | ILOAD x\i, (RISCV_ISIZE * \i)(a0) |
1174 | .endr |
1175 | ILOAD x10, (RISCV_ISIZE * 10)(a0) // restore a0 |
1176 | |
1177 | ret // jump to ra |
1178 | |
1179 | #elif defined(__s390x__) |
1180 | |
1181 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_s390x6jumptoEv) |
1182 | // |
1183 | // void libunwind::Registers_s390x::jumpto() |
1184 | // |
1185 | // On entry: |
1186 | // thread_state pointer is in r2 |
1187 | // |
1188 | |
1189 | // Skip PSWM, but load PSWA into r1 |
1190 | lg %r1, 8(%r2) |
1191 | |
1192 | // Restore FPRs |
1193 | .irp i,FROM_0_TO_15 |
1194 | ld %f\i, (144+8*\i)(%r2) |
1195 | .endr |
1196 | |
1197 | // Restore GPRs - skipping %r0 and %r1 |
1198 | lmg %r2, %r15, 32(%r2) |
1199 | |
1200 | // Return to PSWA (was loaded into %r1 above) |
1201 | br %r1 |
1202 | |
1203 | #elif defined(__loongarch__) && __loongarch_grlen == 64 |
1204 | |
1205 | // |
1206 | // void libunwind::Registers_loongarch::jumpto() |
1207 | // |
1208 | // On entry: |
1209 | // thread_state pointer is in $a0($r4) |
1210 | // |
1211 | .p2align 2 |
1212 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind19Registers_loongarch6jumptoEv) |
1213 | # if __loongarch_frlen == 64 |
1214 | .irp i,FROM_0_TO_31 |
1215 | fld.d $f\i, $a0, (8 * 33 + 8 * \i) |
1216 | .endr |
1217 | # endif |
1218 | |
1219 | // $r0 is zero |
1220 | .irp i,1,2,3 |
1221 | ld.d $r\i, $a0, (8 * \i) |
1222 | .endr |
1223 | // skip $a0 for now |
1224 | .irp i,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 |
1225 | ld.d $r\i, $a0, (8 * \i) |
1226 | .endr |
1227 | |
1228 | ld.d $ra, $a0, (8 * 32) // load new pc into $ra |
1229 | ld.d $a0, $a0, (8 * 4) // restore $a0 last |
1230 | |
1231 | jr $ra |
1232 | |
1233 | #endif |
1234 | |
1235 | #endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */ |
1236 | |
1237 | NO_EXEC_STACK_DIRECTIVE |
1238 | |
1239 | |