FD.io VPP  v19.04.1-1-ge4a0f9f
Vector Packet Processing
longjmp.S
Go to the documentation of this file.
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