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