mips64: Add timer and longjump support
[vpp.git] / src / vppinfra / longjmp.S
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16   Copyright (c) 2005 Eliot Dresselhaus
17
18   Permission is hereby granted, free of charge, to any person obtaining
19   a copy of this software and associated documentation files (the
20   "Software"), to deal in the Software without restriction, including
21   without limitation the rights to use, copy, modify, merge, publish,
22   distribute, sublicense, and/or sell copies of the Software, and to
23   permit persons to whom the Software is furnished to do so, subject to
24   the following conditions:
25
26   The above copyright notice and this permission notice shall be
27   included in all copies or substantial portions of the Software.
28
29   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 */
37         
38 #if defined(__x86_64__)
39         .global clib_setjmp
40         .align 4
41         .type clib_setjmp, @function
42 clib_setjmp:
43         movq %rbx, 8*0(%rdi)
44         movq %rbp, 8*1(%rdi)
45         movq %r12, 8*2(%rdi)
46         movq %r13, 8*3(%rdi)
47         movq %r14, 8*4(%rdi)
48         movq %r15, 8*5(%rdi)
49
50         /* Save SP after return. */
51         leaq 8(%rsp), %rdx
52         movq %rdx, 8*6(%rdi)
53         
54         /* Save PC we are returning to from stack frame. */
55         movq 0(%rsp), %rax
56         movq %rax, 8*7(%rdi)
57         
58         /* Give back user's return value. */
59         movq %rsi, %rax
60         ret
61         
62         .global clib_longjmp
63         .align 4
64         .type clib_longjmp, @function
65 clib_longjmp:   
66         /* Restore regs. */
67         movq 8*0(%rdi), %rbx
68         movq 8*1(%rdi), %rbp
69         movq 8*2(%rdi), %r12
70         movq 8*3(%rdi), %r13
71         movq 8*4(%rdi), %r14
72         movq 8*5(%rdi), %r15
73         movq 8*6(%rdi), %rsp
74         movq 8*7(%rdi), %rdx
75         
76         /* Give back user's return value. */
77         movq %rsi, %rax
78         
79         /* Away we go. */
80         jmpq *%rdx      
81         
82         .global clib_calljmp
83         .align 4
84         .type clib_calljmp, @function
85 clib_calljmp:
86         /* Make sure stack is 16-byte aligned. */
87         movq %rdx, %rax
88         andq $0xf, %rax
89         subq %rax, %rdx
90         
91         /* Get return address. */
92         pop %rax
93         
94         /* Switch to new stack. */
95         xchgq %rsp, %rdx
96         
97         /* Save return address on new stack. */
98         push %rax
99         
100         /* Save old stack pointer on new stack. */
101         push %rdx
102         
103         /* Get function. */
104         movq %rdi, %rdx
105         
106         /* Move argument into place. */
107         movq %rsi, %rdi
108         
109         /* Away we go. */
110         callq *%rdx
111         
112         /* Switch back to old stack. */
113         movq 8(%rsp), %rdx
114         movq 0(%rsp), %rcx
115         xchgq %rcx, %rsp
116         
117         /* Return to caller. */
118         jmpq *%rdx
119
120 #elif defined(i386)
121         .global clib_setjmp
122         .align 4
123         .type clib_setjmp, @function
124 clib_setjmp:
125         movl 4(%esp), %ecx
126         
127         movl %ebp, 4*0(%ecx)
128         movl %ebx, 4*1(%ecx)
129         movl %edi, 4*2(%ecx)
130         movl %esi, 4*3(%ecx)
131
132         /* Save SP after return. */
133         leal 4(%esp), %edx
134         movl %edx, 4*4(%ecx)
135         
136         /* Save PC we are returning to from stack frame. */
137         movl 0(%esp), %eax
138         movl %eax, 4*5(%ecx)
139         
140         /* Give back user's return value. */
141         movl 8(%esp), %eax
142         ret
143         
144         .global clib_longjmp
145         .align 4
146         .type clib_longjmp, @function
147 clib_longjmp:   
148         movl 4(%esp), %ecx
149         
150         /* Give back user's return value. */
151         movl 8(%esp), %eax
152         
153         /* Restore regs. */
154         movl 4*0(%ecx), %ebp
155         movl 4*1(%ecx), %ebx
156         movl 4*2(%ecx), %edi
157         movl 4*3(%ecx), %esi
158         movl 4*4(%ecx), %esp
159         movl 4*5(%ecx), %edx
160         
161         /* Away we go. */
162         jmp *%edx       
163         
164         .global clib_calljmp
165         .align 4
166         .type clib_calljmp, @function
167 clib_calljmp:   
168         /* Get new stack pointer. */
169         movl 12(%esp), %edx
170         
171         /* Switch stacks. */
172         xchgl %esp, %edx
173         
174         /* Save old stack pointer on new stack. */
175         sub $8, %esp
176         movl %edx, 4(%esp)
177         
178         /* Put function argument in stack frame. */
179         movl 8(%edx), %eax
180         movl %eax, 0(%esp)
181         
182         /* Get function. */
183         movl 4(%edx), %eax
184         
185         /* Away we go. */
186         call *%eax
187         
188         /* Switch back to old stack. */
189         movl 4(%esp), %edx
190         xchgl %edx, %esp
191         
192         /* Return to caller. */
193         ret
194         
195 #elif defined(__SPU__)
196         
197 #elif defined(__powerpc64__)
198         
199         .text
200
201 #define _prologue(n)                            \
202     .align 2 ;                                  \
203     .globl n, .##n ;                            \
204     .section ".opd", "aw" ;                     \
205     .align 3 ;                                  \
206 n:  .quad .##n, .TOC.@tocbase, 0 ;              \
207     .previous ;                                 \
208     .size n, 24 ;                               \
209     .type .##n, @function ;                     \
210 .##n:
211
212 #define _foreach_14_31                                                  \
213 _ (14, 0)  _ (15, 1)  _ (16, 2)  _ (17, 3)  _ (18, 4)  _ (19, 5)        \
214 _ (20, 6)  _ (21, 7)  _ (22, 8)  _ (23, 9)  _ (24, 10) _ (25, 11)       \
215 _ (26, 12) _ (27, 13) _ (28, 14) _ (29, 15) _ (30, 16) _ (31, 17)
216
217 #define _foreach_20_31                                          \
218 _ (20, 0) _ (21, 1) _ (22, 2) _ (23, 3) _ (24, 4)  _ (25, 5)    \
219 _ (26, 6) _ (27, 7) _ (28, 8) _ (29, 9) _ (30, 10) _ (31, 11)
220         
221 #ifdef __ALTIVEC__
222 #define CLIB_POWERPC_ALTIVEC_N_REGS 12
223 #else
224 #define CLIB_POWERPC_ALTIVEC_N_REGS 0
225 #endif
226
227 _prologue (clib_setjmp)
228         mflr 0
229         std 0, 8*0(3)
230         std 1, 8*1(3)
231         std 2, 8*2(3)
232         mfcr 0
233         std 0, 8*3(3)
234         mfspr 0, 256
235         stw 0, 8*4(3)
236         
237         /* gprs 14 - 31 */
238 #define _(a,b) std a, 8*((b) + 4 + 18*0)(3) ; 
239         _foreach_14_31
240 #undef _
241         
242         /* fprs 14 - 31 */
243 #define _(a,b) stfd a, 8*((b) + 4 + 18*1)(3) ; 
244         _foreach_14_31
245 #undef _
246
247 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
248         /* vrs 20 - 31 */
249         li 5, 8*(4 + 18*2)
250 #define _(a,b) stvx a, 5, 3 ; addi 5, 5, 16 ;
251         _foreach_20_31
252 #undef _
253 #endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */
254         
255         /* Return value. */
256         mr 3, 4
257         
258         blr
259         
260 _prologue (clib_longjmp)
261         ld 0, 8*0(3)
262         mtlr 0
263         ld 1, 8*1(3)
264         ld 2, 8*2(3)
265         ld 0, 8*3(3)
266         mtcrf 0xff, 0
267         lwz 0, 8*3(3)
268         mtspr 256, 0
269         
270         /* gprs 14 - 31 */
271 #define _(a,b) ld a, 8*((b) + 4 + 18*0)(3) ; 
272         _foreach_14_31
273 #undef _
274         
275         /* fprs 14 - 31 */
276 #define _(a,b) lfd a, 8*((b) + 4 + 18*1)(3) ; 
277         _foreach_14_31
278 #undef _
279         
280 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
281         /* vrs 20 - 31 */
282         li 5, 8*(4 + 18*2)
283 #define _(a,b) lvx a, 5, 3 ; addi 5, 5, 16 ;
284         _foreach_20_31
285 #undef _
286 #endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */
287         
288         /* Return value. */
289         mr 3, 4
290         
291         blr
292
293         .globl clib_calljmp
294         .section        ".opd","aw"
295         .align 3
296 clib_calljmp:
297         .quad   .L.clib_calljmp,.TOC.@tocbase,0
298         .previous
299         .type   clib_calljmp, @function
300 .L.clib_calljmp:
301         mflr 0
302         mr 9,3
303         std 0,16(1)
304         stdu 1,-112(1)
305 #APP
306         std 1,-8(5)
307         addi 5,5,-256
308         mr 1,5
309 #NO_APP
310         ld 10,0(9)
311         std 2,40(1)
312         mr 3,4
313         mtctr 10
314         ld 11,16(9)
315         ld 2,8(9)
316         bctrl
317         ld 2,40(1)
318 #APP
319         addi 1,1,256
320         ld 1,-8(1)
321 #NO_APP
322         addi 1,1,112
323         ld 0,16(1)
324         mtlr 0
325         blr
326         .long 0
327         .byte 0,0,0,1,128,0,0,0
328         .size   clib_calljmp,.-.L.clib_calljmp
329         
330 #elif defined(__powerpc__)
331         
332 #define _foreach_14_31                                                  \
333 _ (14, 0)  _ (15, 1)  _ (16, 2)  _ (17, 3)  _ (18, 4)  _ (19, 5)        \
334 _ (20, 6)  _ (21, 7)  _ (22, 8)  _ (23, 9)  _ (24, 10) _ (25, 11)       \
335 _ (26, 12) _ (27, 13) _ (28, 14) _ (29, 15) _ (30, 16) _ (31, 17)
336
337 #define _foreach_20_31                                          \
338 _ (20, 0) _ (21, 1) _ (22, 2) _ (23, 3) _ (24, 4)  _ (25, 5)    \
339 _ (26, 6) _ (27, 7) _ (28, 8) _ (29, 9) _ (30, 10) _ (31, 11)
340         
341 #ifdef __ALTIVEC__
342 #define CLIB_POWERPC_ALTIVEC_N_REGS 12
343 #else
344 #define CLIB_POWERPC_ALTIVEC_N_REGS 0
345 #endif
346
347         .global clib_setjmp
348         .align 4
349         .type clib_setjmp, @function
350 clib_setjmp:
351         mflr 0
352         stw 0, 4*0(3)
353         stw 1, 4*1(3)
354         mfcr 0
355         stw 0, 4*2(3)
356 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
357         mfspr 0, 256
358 #endif
359         stw 0, 4*3(3)
360         
361 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
362         li 5, 4*4
363 #define _(a,b) stvx a, 3, 5 ; addi 5, 5, 16 ;
364         _foreach_20_31
365 #undef _
366 #endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */
367         
368         /* gp 14 - 31 */
369 #define _(a,b) stw a,  4*(1*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 0*18)(3) ; 
370         _foreach_14_31
371 #undef _
372         
373         /* fp 14 - 31 */
374 #define _(a,b) stfd a, 4*(2*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 1*18)(3) ;
375         _foreach_14_31
376 #undef _
377
378         /* Return value. */
379         mr 3, 4
380         
381         blr
382         
383         .global clib_longjmp
384         .align 4
385         .type clib_longjmp, @function
386 clib_longjmp:   
387         
388         lwz 0, 4*0(3)
389         mtlr 0
390         lwz 1, 4*1(3)
391         lwz 0, 4*2(3)
392         mtcr 0
393         lwz 0, 4*3(3)
394 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
395         mtspr 256, 0
396 #endif
397         
398 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
399         li 5, 4*4
400 #define _(a,b) lvx a, 3, 5 ; addi 5, 5, 16 ;
401         _foreach_20_31
402 #undef _
403 #endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */
404         
405         /* gp 14 - 31 */
406 #define _(a,b) lwz a, 4*(1*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 0*18)(3) ;
407         _foreach_14_31
408 #undef _
409         
410         /* fp 14 - 31 */
411 #define _(a,b) lfd a, 4*(2*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 1*18)(3) ;
412         _foreach_14_31
413 #undef _
414
415         /* Return value. */
416         mr 3, 4
417         
418         blr
419
420         .global clib_calljmp
421         .align 4
422         .type clib_calljmp, @function
423 clib_calljmp:   
424         /* Make sure stack is 16 byte aligned. */
425         andi. 0, 5, 0xf
426         sub  5, 5, 0
427         addi 5, 5, -16
428         
429         /* Save old stack/link pointer on new stack. */
430         stw 1, 0(5)
431         mflr 0
432         stw 0, 4(5)
433         
434         /* account for (sp, lr) tuple, and keep aligned */
435         addi 5, 5, -16
436         
437         /* Switch stacks. */
438         mr 1, 5
439         
440         /* Move argument into place. */
441         mtctr 3
442         mr 3, 4
443         
444         /* Away we go. */
445         bctrl
446         
447         /* back to our synthetic frame */
448         addi 1,1,16
449         
450         /* Switch back to old stack. */
451         lwz 0, 4(1)
452         mtlr 0
453         lwz 0, 0(1)
454         mr 1, 0
455         
456         /* Return to caller. */
457         blr
458         
459 #elif defined(__arm__)
460         
461         .global clib_setjmp
462         .align 4
463         .type clib_setjmp, %function
464 clib_setjmp:
465         mov ip, r0              /* jmp buffer */
466
467         /* Save integer registers */
468         stmia ip!, {v1-v6, sl, fp, sp, lr}
469         
470 #ifdef __IWMMXT__
471         /* Save the call-preserved iWMMXt registers.  */
472         wstrd wr10, [ip], #8
473         wstrd wr11, [ip], #8
474         wstrd wr12, [ip], #8
475         wstrd wr13, [ip], #8
476         wstrd wr14, [ip], #8
477         wstrd wr15, [ip], #8
478 #endif
479
480         /* Give back user's return value. */
481         mov r0, r1
482         bx lr
483         
484         .global clib_longjmp
485         .align 4
486         .type clib_longjmp, %function
487 clib_longjmp:   
488         mov ip, r0              /* jmp buffer */
489
490         /* Restore integer registers. */
491         ldmia     ip!,  {v1-v6, sl, fp, sp, lr}
492         
493 #ifdef __IWMMXT__
494         /* Save the call-preserved iWMMXt registers.  */
495         wldrd wr10, [ip], #8
496         wldrd wr11, [ip], #8
497         wldrd wr12, [ip], #8
498         wldrd wr13, [ip], #8
499         wldrd wr14, [ip], #8
500         wldrd wr15, [ip], #8
501 #endif
502         
503         /* Give back user's return value. */
504         mov r0, r1
505         bx lr
506
507         .global clib_calljmp
508         .align 4
509         .type clib_calljmp, %function
510 clib_calljmp:   
511         /* Make sure stack is 8 byte aligned. */
512         bic r2, r2, #7
513         
514         /* Allocate space for stack/link pointer on new stack. */
515         sub r2, r2, #8  
516         
517         /* Save old stack/link pointer on new stack. */
518         str sp, [r2, #0]
519         str lr, [r2, #4]
520         
521         /* Switch stacks. */
522         mov sp, r2
523         
524         /* Save function to call. */
525         mov ip, r0
526         
527         /* Move argument into place. */
528         mov r0, r1
529         
530         /* Away we go. */
531         bx ip
532         
533         /* Switch back to old stack. */
534         ldr lr, [sp, #4]
535         ldr ip, [sp, #0]
536         mov sp, ip
537         
538         /* Return to caller. */
539         bx lr
540         
541 #elif defined(__xtensa__)
542         
543         /* FIXME implement if needed. */
544         .global clib_setjmp
545         .align 4
546         .type clib_setjmp, %function
547 clib_setjmp:
548 1:      j 1b
549
550         .global clib_longjmp
551         .align 4
552         .type clib_longjmp, @function
553 clib_longjmp:   
554 1:      j 1b
555         
556         .global clib_calljmp
557         .align 4
558         .type clib_calljmp, %function
559 clib_calljmp:   
560 1:      j 1b
561         
562 #elif defined(__TMS320C6X__)
563         
564         /* FIXME implement if needed. */
565         .global clib_setjmp
566         .align 4
567         .type clib_setjmp, %function
568 clib_setjmp:
569 1:      B       .S1     1b
570
571         .global clib_longjmp
572         .align 4
573         .type clib_longjmp, @function
574 clib_longjmp:   
575 1:      B       .S1     1b
576         
577         .global clib_calljmp
578         .align 4
579         .type clib_calljmp, %function
580 clib_calljmp:   
581 1:      B       .S1     1b
582         
583 #elif defined(_mips) && __mips == 64
584
585         .global clib_setjmp
586         .align 8
587         .type clib_setjmp, %function
588 clib_setjmp:
589         sd $ra, 0($a0)
590         sd $sp, 8($a0)
591         sd $gp, 16($a0)
592         sd $16, 24($a0)
593         sd $17, 32($a0)
594         sd $18, 40($a0)
595         sd $19, 48($a0)
596         sd $20, 56($a0)
597         sd $21, 64($a0)
598         sd $22, 72($a0)
599         sd $23, 80($a0)
600         sd $30, 88($a0)
601         move $v0, $a1
602         jr $ra
603         nop
604
605         .global clib_longjmp
606         .align 8
607         .type clib_longjmp, @function
608 clib_longjmp:
609         move $v0, $a1
610         bne $v0, $0, 1f
611         nop
612         daddu $v0, $v0, 1
613 1:
614         ld $ra, 0($a0)
615         ld $sp, 8($a0)
616         ld $gp, 16($a0)
617         ld $16, 24($a0)
618         ld $17, 32($a0)
619         ld $18, 40($a0)
620         ld $19, 48($a0)
621         ld $20, 56($a0)
622         ld $21, 64($a0)
623         ld $22, 72($a0)
624         ld $23, 80($a0)
625         ld $30, 88($a0)
626         jr $ra
627         nop
628
629         .global clib_calljmp
630         .align 8
631         .type clib_calljmp, %function
632 clib_calljmp:
633         /* Force 16 byte alignment of the new stack */
634         li $t1, -16
635         and $t0, $a2, $t1
636         /* Save old ra/gp/sp on new stack */
637         daddiu $t0, $t0, (-24)
638         sd $ra, 0($t0)
639         sd $gp, 8($t0)
640         sd $sp, 16($t0)
641         /* Switch stacks */
642         move $sp, $t0
643         /* Away we go */
644         move $t9, $a0
645         move $a0, $a1
646         jalr $t9
647         nop
648         /* Switch back to old ra/gp/sp */
649         move $t0, $sp
650         ld $ra, 0($t0)
651         ld $gp, 8($t0)
652         ld $sp, 16($t0)
653         /* Return to caller */
654         jr $ra
655         nop
656
657 #elif defined (__aarch64__)
658 /*
659    Copyright (c) 2011, 2012 ARM Ltd
660    All rights reserved.
661    Redistribution and use in source and binary forms, with or without
662    modification, are permitted provided that the following conditions
663    are met:
664    1. Redistributions of source code must retain the above copyright
665       notice, this list of conditions and the following disclaimer.
666    2. Redistributions in binary form must reproduce the above copyright
667       notice, this list of conditions and the following disclaimer in the
668       documentation and/or other materials provided with the distribution.
669    3. The name of the company may not be used to endorse or promote
670       products derived from this software without specific prior written
671       permission.
672    THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
673    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
674    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
675    IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
676    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
677    TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
678    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
679    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
680    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
681    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
682  */
683 #define GPR_LAYOUT                      \
684         REG_PAIR (x19, x20,  0);        \
685         REG_PAIR (x21, x22, 16);        \
686         REG_PAIR (x23, x24, 32);        \
687         REG_PAIR (x25, x26, 48);        \
688         REG_PAIR (x27, x28, 64);        \
689         REG_PAIR (x29, x30, 80);        \
690         REG_ONE (x16,      96)
691 #define FPR_LAYOUT                      \
692         REG_PAIR ( d8,  d9, 112);       \
693         REG_PAIR (d10, d11, 128);       \
694         REG_PAIR (d12, d13, 144);       \
695         REG_PAIR (d14, d15, 160);
696 // int clib_setjmp (jmp_buf)
697         .global clib_setjmp
698         .type   clib_setjmp, %function
699 clib_setjmp:
700         mov     x16, sp
701 #define REG_PAIR(REG1, REG2, OFFS)      stp REG1, REG2, [x0, OFFS]
702 #define REG_ONE(REG1, OFFS)             str REG1, [x0, OFFS]
703         GPR_LAYOUT
704         FPR_LAYOUT
705 #undef REG_PAIR
706 #undef REG_ONE
707         mov     x0, x1
708         ret
709         .size   clib_setjmp, .-clib_setjmp
710 // void clib_longjmp (jmp_buf, int) __attribute__ ((noreturn))
711         .global clib_longjmp
712         .type   clib_longjmp, %function
713 clib_longjmp:
714 #define REG_PAIR(REG1, REG2, OFFS)      ldp REG1, REG2, [x0, OFFS]
715 #define REG_ONE(REG1, OFFS)             ldr REG1, [x0, OFFS]
716         GPR_LAYOUT
717         FPR_LAYOUT
718 #undef REG_PAIR
719 #undef REG_ONE
720         mov     sp, x16
721         mov     x0, x1
722         // cmp  w1, #0
723         // cinc w0, w1, eq
724         // use br not ret, as ret is guaranteed to mispredict
725         br      x30
726         .size   clib_longjmp, .-clib_longjmp
727
728
729 // void clib_calljmp (x0=function, x1=arg, x2=new_stack)
730         .global clib_calljmp
731         .type   clib_calljmp, %function
732 clib_calljmp:
733         // save fn ptr
734         mov     x3, x0
735         // set up fn arg
736         mov     x0, x1
737         // switch stacks
738         mov     x4, sp
739         
740         // space for saved sp, lr on new stack
741         sub     x2, x2, #16
742         mov     sp, x2
743         
744         // save old sp and link register on new stack
745         str     x4, [sp]
746         str     x30,[sp,#8]
747         mov     x4, sp
748
749         // go there
750         blr     x3
751         
752         // restore old sp and link register
753         mov     x4, sp
754         
755         ldr     x3, [x4]
756         ldr     x30,[x4, #8]
757         mov     sp, x3
758         ret
759         .size   clib_calljmp, .-clib_calljmp
760 #else
761 #error "unknown machine"
762 #endif  
763
764 .section .note.GNU-stack,"",%progbits