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