• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1//===-------------------- UnwindRegistersRestore.S ------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "assembly.h"
11
12  .text
13
14#if !defined(__USING_SJLJ_EXCEPTIONS__)
15
16#if defined(__i386__)
17DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_x866jumptoEv)
18#
19# void libunwind::Registers_x86::jumpto()
20#
21#if defined(_WIN32)
22# On windows, the 'this' pointer is passed in ecx instead of on the stack
23  movl   %ecx, %eax
24#else
25# On entry:
26#  +                       +
27#  +-----------------------+
28#  + thread_state pointer  +
29#  +-----------------------+
30#  + return address        +
31#  +-----------------------+   <-- SP
32#  +                       +
33  movl   4(%esp), %eax
34#endif
35  # set up eax and ret on new stack location
36  movl  28(%eax), %edx # edx holds new stack pointer
37  subl  $8,%edx
38  movl  %edx, 28(%eax)
39  movl  0(%eax), %ebx
40  movl  %ebx, 0(%edx)
41  movl  40(%eax), %ebx
42  movl  %ebx, 4(%edx)
43  # we now have ret and eax pushed onto where new stack will be
44  # restore all registers
45  movl   4(%eax), %ebx
46  movl   8(%eax), %ecx
47  movl  12(%eax), %edx
48  movl  16(%eax), %edi
49  movl  20(%eax), %esi
50  movl  24(%eax), %ebp
51  movl  28(%eax), %esp
52  # skip ss
53  # skip eflags
54  pop    %eax  # eax was already pushed on new stack
55  ret        # eip was already pushed on new stack
56  # skip cs
57  # skip ds
58  # skip es
59  # skip fs
60  # skip gs
61
62#elif defined(__x86_64__)
63
64DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind16Registers_x86_646jumptoEv)
65#
66# void libunwind::Registers_x86_64::jumpto()
67#
68#if defined(_WIN64)
69# On entry, thread_state pointer is in rcx; move it into rdi
70# to share restore code below. Since this routine restores and
71# overwrites all registers, we can use the same registers for
72# pointers and temporaries as on unix even though win64 normally
73# mustn't clobber some of them.
74  movq  %rcx, %rdi
75#else
76# On entry, thread_state pointer is in rdi
77#endif
78
79  movq  56(%rdi), %rax # rax holds new stack pointer
80  subq  $16, %rax
81  movq  %rax, 56(%rdi)
82  movq  32(%rdi), %rbx  # store new rdi on new stack
83  movq  %rbx, 0(%rax)
84  movq  128(%rdi), %rbx # store new rip on new stack
85  movq  %rbx, 8(%rax)
86  # restore all registers
87  movq    0(%rdi), %rax
88  movq    8(%rdi), %rbx
89  movq   16(%rdi), %rcx
90  movq   24(%rdi), %rdx
91  # restore rdi later
92  movq   40(%rdi), %rsi
93  movq   48(%rdi), %rbp
94  # restore rsp later
95  movq   64(%rdi), %r8
96  movq   72(%rdi), %r9
97  movq   80(%rdi), %r10
98  movq   88(%rdi), %r11
99  movq   96(%rdi), %r12
100  movq  104(%rdi), %r13
101  movq  112(%rdi), %r14
102  movq  120(%rdi), %r15
103  # skip rflags
104  # skip cs
105  # skip fs
106  # skip gs
107
108#if defined(_WIN64)
109  movdqu 176(%rdi),%xmm0
110  movdqu 192(%rdi),%xmm1
111  movdqu 208(%rdi),%xmm2
112  movdqu 224(%rdi),%xmm3
113  movdqu 240(%rdi),%xmm4
114  movdqu 256(%rdi),%xmm5
115  movdqu 272(%rdi),%xmm6
116  movdqu 288(%rdi),%xmm7
117  movdqu 304(%rdi),%xmm8
118  movdqu 320(%rdi),%xmm9
119  movdqu 336(%rdi),%xmm10
120  movdqu 352(%rdi),%xmm11
121  movdqu 368(%rdi),%xmm12
122  movdqu 384(%rdi),%xmm13
123  movdqu 400(%rdi),%xmm14
124  movdqu 416(%rdi),%xmm15
125#endif
126  movq  56(%rdi), %rsp  # cut back rsp to new location
127  pop    %rdi      # rdi was saved here earlier
128  ret            # rip was saved here
129
130
131#elif defined(__ppc__)
132
133DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv)
134;
135; void libunwind::Registers_ppc::jumpto()
136;
137; On entry:
138;  thread_state pointer is in r3
139;
140
141  ; restore integral registerrs
142  ; skip r0 for now
143  ; skip r1 for now
144  lwz     r2, 16(r3)
145  ; skip r3 for now
146  ; skip r4 for now
147  ; skip r5 for now
148  lwz     r6, 32(r3)
149  lwz     r7, 36(r3)
150  lwz     r8, 40(r3)
151  lwz     r9, 44(r3)
152  lwz    r10, 48(r3)
153  lwz    r11, 52(r3)
154  lwz    r12, 56(r3)
155  lwz    r13, 60(r3)
156  lwz    r14, 64(r3)
157  lwz    r15, 68(r3)
158  lwz    r16, 72(r3)
159  lwz    r17, 76(r3)
160  lwz    r18, 80(r3)
161  lwz    r19, 84(r3)
162  lwz    r20, 88(r3)
163  lwz    r21, 92(r3)
164  lwz    r22, 96(r3)
165  lwz    r23,100(r3)
166  lwz    r24,104(r3)
167  lwz    r25,108(r3)
168  lwz    r26,112(r3)
169  lwz    r27,116(r3)
170  lwz    r28,120(r3)
171  lwz    r29,124(r3)
172  lwz    r30,128(r3)
173  lwz    r31,132(r3)
174
175  ; restore float registers
176  lfd    f0, 160(r3)
177  lfd    f1, 168(r3)
178  lfd    f2, 176(r3)
179  lfd    f3, 184(r3)
180  lfd    f4, 192(r3)
181  lfd    f5, 200(r3)
182  lfd    f6, 208(r3)
183  lfd    f7, 216(r3)
184  lfd    f8, 224(r3)
185  lfd    f9, 232(r3)
186  lfd    f10,240(r3)
187  lfd    f11,248(r3)
188  lfd    f12,256(r3)
189  lfd    f13,264(r3)
190  lfd    f14,272(r3)
191  lfd    f15,280(r3)
192  lfd    f16,288(r3)
193  lfd    f17,296(r3)
194  lfd    f18,304(r3)
195  lfd    f19,312(r3)
196  lfd    f20,320(r3)
197  lfd    f21,328(r3)
198  lfd    f22,336(r3)
199  lfd    f23,344(r3)
200  lfd    f24,352(r3)
201  lfd    f25,360(r3)
202  lfd    f26,368(r3)
203  lfd    f27,376(r3)
204  lfd    f28,384(r3)
205  lfd    f29,392(r3)
206  lfd    f30,400(r3)
207  lfd    f31,408(r3)
208
209  ; restore vector registers if any are in use
210  lwz    r5,156(r3)  ; test VRsave
211  cmpwi  r5,0
212  beq    Lnovec
213
214  subi  r4,r1,16
215  rlwinm  r4,r4,0,0,27  ; mask low 4-bits
216  ; r4 is now a 16-byte aligned pointer into the red zone
217  ; the _vectorRegisters may not be 16-byte aligned so copy via red zone temp buffer
218
219
220#define LOAD_VECTOR_UNALIGNEDl(_index) \
221  andis.  r0,r5,(1<<(15-_index))  @\
222  beq    Ldone  ## _index     @\
223  lwz    r0, 424+_index*16(r3)  @\
224  stw    r0, 0(r4)        @\
225  lwz    r0, 424+_index*16+4(r3)  @\
226  stw    r0, 4(r4)        @\
227  lwz    r0, 424+_index*16+8(r3)  @\
228  stw    r0, 8(r4)        @\
229  lwz    r0, 424+_index*16+12(r3)@\
230  stw    r0, 12(r4)        @\
231  lvx    v ## _index,0,r4    @\
232Ldone  ## _index:
233
234#define LOAD_VECTOR_UNALIGNEDh(_index) \
235  andi.  r0,r5,(1<<(31-_index))  @\
236  beq    Ldone  ## _index    @\
237  lwz    r0, 424+_index*16(r3)  @\
238  stw    r0, 0(r4)        @\
239  lwz    r0, 424+_index*16+4(r3)  @\
240  stw    r0, 4(r4)        @\
241  lwz    r0, 424+_index*16+8(r3)  @\
242  stw    r0, 8(r4)        @\
243  lwz    r0, 424+_index*16+12(r3)@\
244  stw    r0, 12(r4)        @\
245  lvx    v ## _index,0,r4    @\
246  Ldone  ## _index:
247
248
249  LOAD_VECTOR_UNALIGNEDl(0)
250  LOAD_VECTOR_UNALIGNEDl(1)
251  LOAD_VECTOR_UNALIGNEDl(2)
252  LOAD_VECTOR_UNALIGNEDl(3)
253  LOAD_VECTOR_UNALIGNEDl(4)
254  LOAD_VECTOR_UNALIGNEDl(5)
255  LOAD_VECTOR_UNALIGNEDl(6)
256  LOAD_VECTOR_UNALIGNEDl(7)
257  LOAD_VECTOR_UNALIGNEDl(8)
258  LOAD_VECTOR_UNALIGNEDl(9)
259  LOAD_VECTOR_UNALIGNEDl(10)
260  LOAD_VECTOR_UNALIGNEDl(11)
261  LOAD_VECTOR_UNALIGNEDl(12)
262  LOAD_VECTOR_UNALIGNEDl(13)
263  LOAD_VECTOR_UNALIGNEDl(14)
264  LOAD_VECTOR_UNALIGNEDl(15)
265  LOAD_VECTOR_UNALIGNEDh(16)
266  LOAD_VECTOR_UNALIGNEDh(17)
267  LOAD_VECTOR_UNALIGNEDh(18)
268  LOAD_VECTOR_UNALIGNEDh(19)
269  LOAD_VECTOR_UNALIGNEDh(20)
270  LOAD_VECTOR_UNALIGNEDh(21)
271  LOAD_VECTOR_UNALIGNEDh(22)
272  LOAD_VECTOR_UNALIGNEDh(23)
273  LOAD_VECTOR_UNALIGNEDh(24)
274  LOAD_VECTOR_UNALIGNEDh(25)
275  LOAD_VECTOR_UNALIGNEDh(26)
276  LOAD_VECTOR_UNALIGNEDh(27)
277  LOAD_VECTOR_UNALIGNEDh(28)
278  LOAD_VECTOR_UNALIGNEDh(29)
279  LOAD_VECTOR_UNALIGNEDh(30)
280  LOAD_VECTOR_UNALIGNEDh(31)
281
282Lnovec:
283  lwz    r0, 136(r3) ; __cr
284  mtocrf  255,r0
285  lwz    r0, 148(r3) ; __ctr
286  mtctr  r0
287  lwz    r0, 0(r3)  ; __ssr0
288  mtctr  r0
289  lwz    r0, 8(r3)  ; do r0 now
290  lwz    r5,28(r3)  ; do r5 now
291  lwz    r4,24(r3)  ; do r4 now
292  lwz    r1,12(r3)  ; do sp now
293  lwz    r3,20(r3)  ; do r3 last
294  bctr
295
296#elif defined(__arm64__) || defined(__aarch64__)
297
298//
299// void libunwind::Registers_arm64::jumpto()
300//
301// On entry:
302//  thread_state pointer is in x0
303//
304  .p2align 2
305DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv)
306  // skip restore of x0,x1 for now
307  ldp    x2, x3,  [x0, #0x010]
308  ldp    x4, x5,  [x0, #0x020]
309  ldp    x6, x7,  [x0, #0x030]
310  ldp    x8, x9,  [x0, #0x040]
311  ldp    x10,x11, [x0, #0x050]
312  ldp    x12,x13, [x0, #0x060]
313  ldp    x14,x15, [x0, #0x070]
314  ldp    x16,x17, [x0, #0x080]
315  ldp    x18,x19, [x0, #0x090]
316  ldp    x20,x21, [x0, #0x0A0]
317  ldp    x22,x23, [x0, #0x0B0]
318  ldp    x24,x25, [x0, #0x0C0]
319  ldp    x26,x27, [x0, #0x0D0]
320  ldp    x28,x29, [x0, #0x0E0]
321  ldr    x30,     [x0, #0x100]  // restore pc into lr
322  ldr    x1,      [x0, #0x0F8]
323  mov    sp,x1                  // restore sp
324
325  ldp    d0, d1,  [x0, #0x110]
326  ldp    d2, d3,  [x0, #0x120]
327  ldp    d4, d5,  [x0, #0x130]
328  ldp    d6, d7,  [x0, #0x140]
329  ldp    d8, d9,  [x0, #0x150]
330  ldp    d10,d11, [x0, #0x160]
331  ldp    d12,d13, [x0, #0x170]
332  ldp    d14,d15, [x0, #0x180]
333  ldp    d16,d17, [x0, #0x190]
334  ldp    d18,d19, [x0, #0x1A0]
335  ldp    d20,d21, [x0, #0x1B0]
336  ldp    d22,d23, [x0, #0x1C0]
337  ldp    d24,d25, [x0, #0x1D0]
338  ldp    d26,d27, [x0, #0x1E0]
339  ldp    d28,d29, [x0, #0x1F0]
340  ldr    d30,     [x0, #0x200]
341  ldr    d31,     [x0, #0x208]
342
343  ldp    x0, x1,  [x0, #0x000]  // restore x0,x1
344  ret    x30                    // jump to pc
345
346#elif defined(__arm__) && !defined(__APPLE__)
347
348#if !defined(__ARM_ARCH_ISA_ARM)
349  .thumb
350#endif
351
352@
353@ void libunwind::Registers_arm::restoreCoreAndJumpTo()
354@
355@ On entry:
356@  thread_state pointer is in r0
357@
358  .p2align 2
359DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm20restoreCoreAndJumpToEv)
360#if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1
361  @ r8-r11: ldm into r1-r4, then mov to r8-r11
362  adds r0, #0x20
363  ldm r0!, {r1-r4}
364  subs r0, #0x30
365  mov r8, r1
366  mov r9, r2
367  mov r10, r3
368  mov r11, r4
369  @ r12 does not need loading, it it the intra-procedure-call scratch register
370  ldr r2, [r0, #0x34]
371  ldr r3, [r0, #0x3c]
372  mov sp, r2
373  mov lr, r3         @ restore pc into lr
374  ldm r0, {r0-r7}
375#else
376  @ Use lr as base so that r0 can be restored.
377  mov lr, r0
378  @ 32bit thumb-2 restrictions for ldm:
379  @ . the sp (r13) cannot be in the list
380  @ . the pc (r15) and lr (r14) cannot both be in the list in an LDM instruction
381  ldm lr, {r0-r12}
382  ldr sp, [lr, #52]
383  ldr lr, [lr, #60]  @ restore pc into lr
384#endif
385  JMP(lr)
386
387@
388@ static void libunwind::Registers_arm::restoreVFPWithFLDMD(unw_fpreg_t* values)
389@
390@ On entry:
391@  values pointer is in r0
392@
393  .p2align 2
394#if defined(__ELF__)
395  .fpu vfpv3-d16
396#endif
397DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMDEPy)
398  @ VFP and iwMMX instructions are only available when compiling with the flags
399  @ that enable them. We do not want to do that in the library (because we do not
400  @ want the compiler to generate instructions that access those) but this is
401  @ only accessed if the personality routine needs these registers. Use of
402  @ these registers implies they are, actually, available on the target, so
403  @ it's ok to execute.
404  @ So, generate the instruction using the corresponding coprocessor mnemonic.
405  vldmia r0, {d0-d15}
406  JMP(lr)
407
408@
409@ static void libunwind::Registers_arm::restoreVFPWithFLDMX(unw_fpreg_t* values)
410@
411@ On entry:
412@  values pointer is in r0
413@
414  .p2align 2
415#if defined(__ELF__)
416  .fpu vfpv3-d16
417#endif
418DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMXEPy)
419  vldmia r0, {d0-d15} @ fldmiax is deprecated in ARMv7+ and now behaves like vldmia
420  JMP(lr)
421
422@
423@ static void libunwind::Registers_arm::restoreVFPv3(unw_fpreg_t* values)
424@
425@ On entry:
426@  values pointer is in r0
427@
428  .p2align 2
429#if defined(__ELF__)
430  .fpu vfpv3
431#endif
432DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPy)
433  vldmia r0, {d16-d31}
434  JMP(lr)
435
436#if defined(__ARM_WMMX)
437
438@
439@ static void libunwind::Registers_arm::restoreiWMMX(unw_fpreg_t* values)
440@
441@ On entry:
442@  values pointer is in r0
443@
444  .p2align 2
445#if defined(__ELF__)
446  .arch armv5te
447#endif
448DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPy)
449  ldcl p1, cr0, [r0], #8  @ wldrd wR0, [r0], #8
450  ldcl p1, cr1, [r0], #8  @ wldrd wR1, [r0], #8
451  ldcl p1, cr2, [r0], #8  @ wldrd wR2, [r0], #8
452  ldcl p1, cr3, [r0], #8  @ wldrd wR3, [r0], #8
453  ldcl p1, cr4, [r0], #8  @ wldrd wR4, [r0], #8
454  ldcl p1, cr5, [r0], #8  @ wldrd wR5, [r0], #8
455  ldcl p1, cr6, [r0], #8  @ wldrd wR6, [r0], #8
456  ldcl p1, cr7, [r0], #8  @ wldrd wR7, [r0], #8
457  ldcl p1, cr8, [r0], #8  @ wldrd wR8, [r0], #8
458  ldcl p1, cr9, [r0], #8  @ wldrd wR9, [r0], #8
459  ldcl p1, cr10, [r0], #8  @ wldrd wR10, [r0], #8
460  ldcl p1, cr11, [r0], #8  @ wldrd wR11, [r0], #8
461  ldcl p1, cr12, [r0], #8  @ wldrd wR12, [r0], #8
462  ldcl p1, cr13, [r0], #8  @ wldrd wR13, [r0], #8
463  ldcl p1, cr14, [r0], #8  @ wldrd wR14, [r0], #8
464  ldcl p1, cr15, [r0], #8  @ wldrd wR15, [r0], #8
465  JMP(lr)
466
467@
468@ static void libunwind::Registers_arm::restoreiWMMXControl(unw_uint32_t* values)
469@
470@ On entry:
471@  values pointer is in r0
472@
473  .p2align 2
474#if defined(__ELF__)
475  .arch armv5te
476#endif
477DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreiWMMXControlEPj)
478  ldc2 p1, cr8, [r0], #4  @ wldrw wCGR0, [r0], #4
479  ldc2 p1, cr9, [r0], #4  @ wldrw wCGR1, [r0], #4
480  ldc2 p1, cr10, [r0], #4  @ wldrw wCGR2, [r0], #4
481  ldc2 p1, cr11, [r0], #4  @ wldrw wCGR3, [r0], #4
482  JMP(lr)
483
484#endif
485
486#elif defined(__or1k__)
487
488DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv)
489#
490# void libunwind::Registers_or1k::jumpto()
491#
492# On entry:
493#  thread_state pointer is in r3
494#
495
496  # restore integral registerrs
497  l.lwz     r0,  0(r3)
498  l.lwz     r1,  4(r3)
499  l.lwz     r2,  8(r3)
500  # skip r3 for now
501  l.lwz     r4, 16(r3)
502  l.lwz     r5, 20(r3)
503  l.lwz     r6, 24(r3)
504  l.lwz     r7, 28(r3)
505  l.lwz     r8, 32(r3)
506  l.lwz     r9, 36(r3)
507  l.lwz    r10, 40(r3)
508  l.lwz    r11, 44(r3)
509  l.lwz    r12, 48(r3)
510  l.lwz    r13, 52(r3)
511  l.lwz    r14, 56(r3)
512  l.lwz    r15, 60(r3)
513  l.lwz    r16, 64(r3)
514  l.lwz    r17, 68(r3)
515  l.lwz    r18, 72(r3)
516  l.lwz    r19, 76(r3)
517  l.lwz    r20, 80(r3)
518  l.lwz    r21, 84(r3)
519  l.lwz    r22, 88(r3)
520  l.lwz    r23, 92(r3)
521  l.lwz    r24, 96(r3)
522  l.lwz    r25,100(r3)
523  l.lwz    r26,104(r3)
524  l.lwz    r27,108(r3)
525  l.lwz    r28,112(r3)
526  l.lwz    r29,116(r3)
527  l.lwz    r30,120(r3)
528  l.lwz    r31,124(r3)
529
530  # at last, restore r3
531  l.lwz    r3,  12(r3)
532
533  # jump to pc
534  l.jr     r9
535   l.nop
536
537#elif defined(__mips__) && defined(_ABIO32) && defined(__mips_soft_float)
538
539//
540// void libunwind::Registers_mips_o32::jumpto()
541//
542// On entry:
543//  thread state pointer is in a0 ($4)
544//
545DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv)
546  .set push
547  .set noat
548  .set noreorder
549  .set nomacro
550  // restore hi and lo
551  lw    $8, (4 * 33)($4)
552  mthi  $8
553  lw    $8, (4 * 34)($4)
554  mtlo  $8
555  // r0 is zero
556  lw    $1, (4 * 1)($4)
557  lw    $2, (4 * 2)($4)
558  lw    $3, (4 * 3)($4)
559  // skip a0 for now
560  lw    $5, (4 * 5)($4)
561  lw    $6, (4 * 6)($4)
562  lw    $7, (4 * 7)($4)
563  lw    $8, (4 * 8)($4)
564  lw    $9, (4 * 9)($4)
565  lw    $10, (4 * 10)($4)
566  lw    $11, (4 * 11)($4)
567  lw    $12, (4 * 12)($4)
568  lw    $13, (4 * 13)($4)
569  lw    $14, (4 * 14)($4)
570  lw    $15, (4 * 15)($4)
571  lw    $16, (4 * 16)($4)
572  lw    $17, (4 * 17)($4)
573  lw    $18, (4 * 18)($4)
574  lw    $19, (4 * 19)($4)
575  lw    $20, (4 * 20)($4)
576  lw    $21, (4 * 21)($4)
577  lw    $22, (4 * 22)($4)
578  lw    $23, (4 * 23)($4)
579  lw    $24, (4 * 24)($4)
580  lw    $25, (4 * 25)($4)
581  lw    $26, (4 * 26)($4)
582  lw    $27, (4 * 27)($4)
583  lw    $28, (4 * 28)($4)
584  lw    $29, (4 * 29)($4)
585  lw    $30, (4 * 30)($4)
586  // load new pc into ra
587  lw    $31, (4 * 32)($4)
588  // jump to ra, load a0 in the delay slot
589  jr    $31
590  lw    $4, (4 * 4)($4)
591  .set pop
592
593#elif defined(__mips__) && defined(_ABI64) && defined(__mips_soft_float)
594
595//
596// void libunwind::Registers_mips_n64::jumpto()
597//
598// On entry:
599//  thread state pointer is in a0 ($4)
600//
601DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind18Registers_mips_n646jumptoEv)
602  .set push
603  .set noat
604  .set noreorder
605  .set nomacro
606  // restore hi and lo
607  ld    $8, (8 * 33)($4)
608  mthi  $8
609  ld    $8, (8 * 34)($4)
610  mtlo  $8
611  // r0 is zero
612  ld    $1, (8 * 1)($4)
613  ld    $2, (8 * 2)($4)
614  ld    $3, (8 * 3)($4)
615  // skip a0 for now
616  ld    $5, (8 * 5)($4)
617  ld    $6, (8 * 6)($4)
618  ld    $7, (8 * 7)($4)
619  ld    $8, (8 * 8)($4)
620  ld    $9, (8 * 9)($4)
621  ld    $10, (8 * 10)($4)
622  ld    $11, (8 * 11)($4)
623  ld    $12, (8 * 12)($4)
624  ld    $13, (8 * 13)($4)
625  ld    $14, (8 * 14)($4)
626  ld    $15, (8 * 15)($4)
627  ld    $16, (8 * 16)($4)
628  ld    $17, (8 * 17)($4)
629  ld    $18, (8 * 18)($4)
630  ld    $19, (8 * 19)($4)
631  ld    $20, (8 * 20)($4)
632  ld    $21, (8 * 21)($4)
633  ld    $22, (8 * 22)($4)
634  ld    $23, (8 * 23)($4)
635  ld    $24, (8 * 24)($4)
636  ld    $25, (8 * 25)($4)
637  ld    $26, (8 * 26)($4)
638  ld    $27, (8 * 27)($4)
639  ld    $28, (8 * 28)($4)
640  ld    $29, (8 * 29)($4)
641  ld    $30, (8 * 30)($4)
642  // load new pc into ra
643  ld    $31, (8 * 32)($4)
644  // jump to ra, load a0 in the delay slot
645  jr    $31
646  ld    $4, (8 * 4)($4)
647  .set pop
648
649#endif
650
651#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */
652
653NO_EXEC_STACK_DIRECTIVE
654
655