FD.io VPP  v21.01.1
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 #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 #if _CALL_ELF == 2
228 
229 #define _prologue(n) \
230  .globl n ; \
231  .p2align 4 ; \
232  .type n, @function ; \
233 n: ; \
234 .L##n##_begin: ;
235 
236 #define _gep_lep(n) \
237 .L##n##_gep: ; \
238  addis 2, 12, .TOC.-.L##n##_gep@ha ; \
239  addi 2, 2, .TOC.-.L##n##_gep@l ; \
240 .L##n##_lep: ; \
241  .localentry n, .L##n##_lep-.L##n##_gep
242 
243 #else /* _CALL_ELF == 1 */
244 
245 #define _prologue(n) \
246  .globl n ; \
247  .p2align 4 ; \
248  .type .##n, @function ; \
249  .section ".opd", "aw" ,@progbits ; \
250 n: ; \
251  .p2align 3 ; \
252  .quad .L##n##_begin ; \
253  .quad .TOC.@tocbase ; \
254  .quad 0 ; \
255  .text ; \
256 .L##n##_begin: ;
257 
258 #endif
259 
260 #define _epilogue(n) \
261  .long 0 ; \
262  .quad 0 ; \
263 .L##n##_end: ; \
264  .size n, .L##n##_end-.L##n##_begin
265 
266 #if _CALL_ELF == 2
267  .abiversion 2
268  .section ".text"
269 #else
270  .text
271 #endif
272 
273 _prologue(clib_setjmp)
274  mflr 0
275  std 0, 8*0(3)
276  std 1, 8*1(3)
277  std 2, 8*2(3)
278  mfcr 0
279  std 0, 8*3(3)
280  mfspr 0, 256
281  stw 0, 8*4(3)
282 
283  /* gprs 14 - 31 */
284 #define _(a,b) std a, 8*((b) + 4 + 18*0)(3) ;
285  _foreach_14_31
286 #undef _
287 
288  /* fprs 14 - 31 */
289 #define _(a,b) stfd 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) stvx 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  blr
304 _epilogue(clib_setjmp)
305 
306 _prologue(clib_longjmp)
307  ld 0, 8*0(3)
308  mtlr 0
309  ld 1, 8*1(3)
310  ld 2, 8*2(3)
311  ld 0, 8*3(3)
312  mtcrf 0xff, 0
313  lwz 0, 8*3(3)
314  mtspr 256, 0
315 
316  /* gprs 14 - 31 */
317 #define _(a,b) ld a, 8*((b) + 4 + 18*0)(3) ;
318  _foreach_14_31
319 #undef _
320 
321  /* fprs 14 - 31 */
322 #define _(a,b) lfd a, 8*((b) + 4 + 18*1)(3) ;
323  _foreach_14_31
324 #undef _
325 
326 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
327  /* vrs 20 - 31 */
328  li 5, 8*(4 + 18*2)
329 #define _(a,b) lvx a, 5, 3 ; addi 5, 5, 16 ;
330  _foreach_20_31
331 #undef _
332 #endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */
333 
334  /* Return value. */
335  mr 3, 4
336  blr
337 _epilogue(clib_longjmp)
338 
339 #if _CALL_ELF == 2
340 _prologue(clib_calljmp)
341 _gep_lep(clib_calljmp)
342  mflr 0 /* get link register into r0 */
343  std 0,16(1) /* store r0 into the stack frame */
344  stdu 1,-32(1) /* move sp down for one frame */
345  mr 12,3 /* move func pointer to r12 */
346  mr 3,4 /* pass func_arg as first arg */
347  std 1,-8(5) /* store old sp into the top of the new stack */
348  addi 5,5,-256 /* stack_addr =- 256 */
349  mr 1,5 /* set new sp */
350  mtctr 12 /* put function pointer into CTR register */
351  std 2,24(1) /* store TOC pointer into stack frame */
352  bctrl /* unconditional branch to counter register */
353  ld 2,24(1) /* load TOC pointer from stack frame */
354  addi 1,1,256 /* go back to the start of the new stack */
355  ld 1,-8(1) /* load old sp */
356  addi 1,1,32 /* move sp back to previous frame */
357  ld 0,16(1) /* get old link reg value from the stack */
358  mtlr 0 /* restore link reg value */
359  blr
360 _epilogue(clib_calljmp)
361 
362 #else /* v1 ABI */
363 
364 _prologue(clib_calljmp)
365  mflr 0 /* get link register into r0 */
366  mr 9,3 /* store function pointer into the r9 */
367  std 0,16(1) /* store r0 into the stack frame */
368  stdu 1,-112(1) /* move sp down for one frame */
369  std 1,-8(5) /* store old sp into the top of the new stack */
370  addi 5,5,-256 /* stack_addr =- 256 */
371  mr 1,5 /* set new sp */
372  ld 10,0(9)
373  std 2,40(1) /* store TOC pointer into the stack */
374  mr 3,4
375  mtctr 10
376  ld 11,16(9)
377  ld 2,8(9)
378  bctrl /* unconditional branch to counter register */
379  ld 2,40(1) /* load TOC pointer from the stack */
380  addi 1,1,256 /* go back to the start of the new stack */
381  ld 1,-8(1) /* load the old sp */
382  addi 1,1,112 /* move sp back to previous frame */
383  ld 0,16(1) /* restore link register from the stack frame */
384  mtlr 0
385  blr
386 _epilogue(clib_calljmp)
387 
388 #endif
389 #elif defined(__powerpc__)
390 
391 #define _foreach_14_31 \
392 _ (14, 0) _ (15, 1) _ (16, 2) _ (17, 3) _ (18, 4) _ (19, 5) \
393 _ (20, 6) _ (21, 7) _ (22, 8) _ (23, 9) _ (24, 10) _ (25, 11) \
394 _ (26, 12) _ (27, 13) _ (28, 14) _ (29, 15) _ (30, 16) _ (31, 17)
395 
396 #define _foreach_20_31 \
397 _ (20, 0) _ (21, 1) _ (22, 2) _ (23, 3) _ (24, 4) _ (25, 5) \
398 _ (26, 6) _ (27, 7) _ (28, 8) _ (29, 9) _ (30, 10) _ (31, 11)
399 
400 #ifdef __ALTIVEC__
401 #define CLIB_POWERPC_ALTIVEC_N_REGS 12
402 #else
403 #define CLIB_POWERPC_ALTIVEC_N_REGS 0
404 #endif
405 
406  .global cdecl(clib_setjmp)
407  .align 4
408  .type cdecl(clib_setjmp), @function
409 cdecl(clib_setjmp):
410  mflr 0
411  stw 0, 4*0(3)
412  stw 1, 4*1(3)
413  mfcr 0
414  stw 0, 4*2(3)
415 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
416  mfspr 0, 256
417 #endif
418  stw 0, 4*3(3)
419 
420 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
421  li 5, 4*4
422 #define _(a,b) stvx a, 3, 5 ; addi 5, 5, 16 ;
423  _foreach_20_31
424 #undef _
425 #endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */
426 
427  /* gp 14 - 31 */
428 #define _(a,b) stw a, 4*(1*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 0*18)(3) ;
429  _foreach_14_31
430 #undef _
431 
432  /* fp 14 - 31 */
433 #define _(a,b) stfd a, 4*(2*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 1*18)(3) ;
434  _foreach_14_31
435 #undef _
436 
437  /* Return value. */
438  mr 3, 4
439 
440  blr
441 
442  .global cdecl(clib_longjmp)
443  .align 4
444  .type cdecl(clib_longjmp), @function
445 cdecl(clib_longjmp):
446 
447  lwz 0, 4*0(3)
448  mtlr 0
449  lwz 1, 4*1(3)
450  lwz 0, 4*2(3)
451  mtcr 0
452  lwz 0, 4*3(3)
453 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
454  mtspr 256, 0
455 #endif
456 
457 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
458  li 5, 4*4
459 #define _(a,b) lvx a, 3, 5 ; addi 5, 5, 16 ;
460  _foreach_20_31
461 #undef _
462 #endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */
463 
464  /* gp 14 - 31 */
465 #define _(a,b) lwz a, 4*(1*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 0*18)(3) ;
466  _foreach_14_31
467 #undef _
468 
469  /* fp 14 - 31 */
470 #define _(a,b) lfd a, 4*(2*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 1*18)(3) ;
471  _foreach_14_31
472 #undef _
473 
474  /* Return value. */
475  mr 3, 4
476 
477  blr
478 
479  .global cdecl(clib_calljmp)
480  .align 4
481  .type cdecl(clib_calljmp), @function
482 cdecl(clib_calljmp):
483  /* Make sure stack is 16 byte aligned. */
484  andi. 0, 5, 0xf
485  sub 5, 5, 0
486  addi 5, 5, -16
487 
488  /* Save old stack/link pointer on new stack. */
489  stw 1, 0(5)
490  mflr 0
491  stw 0, 4(5)
492 
493  /* account for (sp, lr) tuple, and keep aligned */
494  addi 5, 5, -16
495 
496  /* Switch stacks. */
497  mr 1, 5
498 
499  /* Move argument into place. */
500  mtctr 3
501  mr 3, 4
502 
503  /* Away we go. */
504  bctrl
505 
506  /* back to our synthetic frame */
507  addi 1,1,16
508 
509  /* Switch back to old stack. */
510  lwz 0, 4(1)
511  mtlr 0
512  lwz 0, 0(1)
513  mr 1, 0
514 
515  /* Return to caller. */
516  blr
517 
518 #elif defined(__arm__)
519 
520  .global cdecl(clib_setjmp)
521  .align 4
522  .type cdecl(clib_setjmp), %function
523 cdecl(clib_setjmp):
524  mov ip, r0 /* jmp buffer */
525 
526  /* Save integer registers */
527  stmia ip!, {v1-v6, sl, fp, sp, lr}
528 
529 #ifdef __IWMMXT__
530  /* Save the call-preserved iWMMXt registers. */
531  wstrd wr10, [ip], #8
532  wstrd wr11, [ip], #8
533  wstrd wr12, [ip], #8
534  wstrd wr13, [ip], #8
535  wstrd wr14, [ip], #8
536  wstrd wr15, [ip], #8
537 #endif
538 
539  /* Give back user's return value. */
540  mov r0, r1
541  bx lr
542 
543  .global cdecl(clib_longjmp)
544  .align 4
545  .type cdecl(clib_longjmp), %function
546 cdecl(clib_longjmp):
547  mov ip, r0 /* jmp buffer */
548 
549  /* Restore integer registers. */
550  ldmia ip!, {v1-v6, sl, fp, sp, lr}
551 
552 #ifdef __IWMMXT__
553  /* Save the call-preserved iWMMXt registers. */
554  wldrd wr10, [ip], #8
555  wldrd wr11, [ip], #8
556  wldrd wr12, [ip], #8
557  wldrd wr13, [ip], #8
558  wldrd wr14, [ip], #8
559  wldrd wr15, [ip], #8
560 #endif
561 
562  /* Give back user's return value. */
563  mov r0, r1
564  bx lr
565 
566  .global cdecl(clib_calljmp)
567  .align 4
568  .type cdecl(clib_calljmp), %function
569 cdecl(clib_calljmp):
570  /* Make sure stack is 8 byte aligned. */
571  bic r2, r2, #7
572 
573  /* Allocate space for stack/link pointer on new stack. */
574  sub r2, r2, #8
575 
576  /* Save old stack/link pointer on new stack. */
577  str sp, [r2, #0]
578  str lr, [r2, #4]
579 
580  /* Switch stacks. */
581  mov sp, r2
582 
583  /* Save function to call. */
584  mov ip, r0
585 
586  /* Move argument into place. */
587  mov r0, r1
588 
589  /* Away we go. */
590  bx ip
591 
592  /* Switch back to old stack. */
593  ldr lr, [sp, #4]
594  ldr ip, [sp, #0]
595  mov sp, ip
596 
597  /* Return to caller. */
598  bx lr
599 
600 #elif defined(__xtensa__)
601 
602  /* FIXME implement if needed. */
603  .global cdecl(clib_setjmp)
604  .align 4
605  .type cdecl(clib_setjmp), %function
606 cdecl(clib_setjmp):
607 1: j 1b
608 
609  .global cdecl(clib_longjmp)
610  .align 4
611  .type cdecl(clib_longjmp), @function
612 cdecl(clib_longjmp):
613 1: j 1b
614 
615  .global cdecl(clib_calljmp)
616  .align 4
617  .type cdecl(clib_calljmp), %function
618 cdecl(clib_calljmp):
619 1: j 1b
620 
621 #elif defined(__TMS320C6X__)
622 
623  /* FIXME implement if needed. */
624  .global cdecl(clib_setjmp)
625  .align 4
626  .type cdecl(clib_setjmp), %function
627 cdecl(clib_setjmp):
628 1: B .S1 1b
629 
630  .global cdecl(clib_longjmp)
631  .align 4
632  .type cdecl(clib_longjmp), @function
633 cdecl(clib_longjmp):
634 1: B .S1 1b
635 
636  .global cdecl(clib_calljmp)
637  .align 4
638  .type cdecl(clib_calljmp), %function
639 cdecl(clib_calljmp):
640 1: B .S1 1b
641 
642 #elif defined(_mips) && __mips == 64
643 
644  .global cdecl(clib_setjmp)
645  .align 8
646  .type cdecl(clib_setjmp), %function
647 cdecl(clib_setjmp):
648  sd $ra, 0($a0)
649  sd $sp, 8($a0)
650  sd $gp, 16($a0)
651  sd $16, 24($a0)
652  sd $17, 32($a0)
653  sd $18, 40($a0)
654  sd $19, 48($a0)
655  sd $20, 56($a0)
656  sd $21, 64($a0)
657  sd $22, 72($a0)
658  sd $23, 80($a0)
659  sd $30, 88($a0)
660  move $v0, $a1
661  jr $ra
662  nop
663 
664  .global cdecl(clib_longjmp)
665  .align 8
666  .type cdecl(clib_longjmp), @function
667 cdecl(clib_longjmp):
668  move $v0, $a1
669  bne $v0, $0, 1f
670  nop
671  daddu $v0, $v0, 1
672 1:
673  ld $ra, 0($a0)
674  ld $sp, 8($a0)
675  ld $gp, 16($a0)
676  ld $16, 24($a0)
677  ld $17, 32($a0)
678  ld $18, 40($a0)
679  ld $19, 48($a0)
680  ld $20, 56($a0)
681  ld $21, 64($a0)
682  ld $22, 72($a0)
683  ld $23, 80($a0)
684  ld $30, 88($a0)
685  jr $ra
686  nop
687 
688  .global cdecl(clib_calljmp)
689  .align 8
690  .type cdecl(clib_calljmp), %function
691 cdecl(clib_calljmp):
692  /* Force 16 byte alignment of the new stack */
693  li $t1, -16
694  and $t0, $a2, $t1
695  /* Save old ra/gp/sp on new stack */
696  daddiu $t0, $t0, (-24)
697  sd $ra, 0($t0)
698  sd $gp, 8($t0)
699  sd $sp, 16($t0)
700  /* Switch stacks */
701  move $sp, $t0
702  /* Away we go */
703  move $t9, $a0
704  move $a0, $a1
705  jalr $t9
706  nop
707  /* Switch back to old ra/gp/sp */
708  move $t0, $sp
709  ld $ra, 0($t0)
710  ld $gp, 8($t0)
711  ld $sp, 16($t0)
712  /* Return to caller */
713  jr $ra
714  nop
715 
716 #elif defined (__aarch64__)
717 /*
718  Copyright (c) 2011, 2012 ARM Ltd
719  All rights reserved.
720  Redistribution and use in source and binary forms, with or without
721  modification, are permitted provided that the following conditions
722  are met:
723  1. Redistributions of source code must retain the above copyright
724  notice, this list of conditions and the following disclaimer.
725  2. Redistributions in binary form must reproduce the above copyright
726  notice, this list of conditions and the following disclaimer in the
727  documentation and/or other materials provided with the distribution.
728  3. The name of the company may not be used to endorse or promote
729  products derived from this software without specific prior written
730  permission.
731  THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
732  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
733  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
734  IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
735  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
736  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
737  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
738  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
739  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
740  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
741  */
742 #define GPR_LAYOUT \
743  REG_PAIR (x19, x20, 0); \
744  REG_PAIR (x21, x22, 16); \
745  REG_PAIR (x23, x24, 32); \
746  REG_PAIR (x25, x26, 48); \
747  REG_PAIR (x27, x28, 64); \
748  REG_PAIR (x29, x30, 80); \
749  REG_ONE (x16, 96)
750 #define FPR_LAYOUT \
751  REG_PAIR ( d8, d9, 112); \
752  REG_PAIR (d10, d11, 128); \
753  REG_PAIR (d12, d13, 144); \
754  REG_PAIR (d14, d15, 160);
755 // int cdecl(clib_setjmp) (jmp_buf)
756  .global cdecl(clib_setjmp)
757  .type cdecl(clib_setjmp), %function
758 cdecl(clib_setjmp):
759  mov x16, sp
760 #define REG_PAIR(REG1, REG2, OFFS) stp REG1, REG2, [x0, OFFS]
761 #define REG_ONE(REG1, OFFS) str REG1, [x0, OFFS]
762  GPR_LAYOUT
763  FPR_LAYOUT
764 #undef REG_PAIR
765 #undef REG_ONE
766  mov x0, x1
767  ret
768  .size cdecl(clib_setjmp), .-cdecl(clib_setjmp)
769 // void cdecl(clib_longjmp) (jmp_buf, int) __attribute__ ((noreturn))
770  .global cdecl(clib_longjmp)
771  .type cdecl(clib_longjmp), %function
772 cdecl(clib_longjmp):
773 #define REG_PAIR(REG1, REG2, OFFS) ldp REG1, REG2, [x0, OFFS]
774 #define REG_ONE(REG1, OFFS) ldr REG1, [x0, OFFS]
775  GPR_LAYOUT
776  FPR_LAYOUT
777 #undef REG_PAIR
778 #undef REG_ONE
779  mov sp, x16
780  mov x0, x1
781  // cmp w1, #0
782  // cinc w0, w1, eq
783  // use br not ret, as ret is guaranteed to mispredict
784  br x30
785  .size cdecl(clib_longjmp), .-cdecl(clib_longjmp)
786 
787 
788 // void cdecl(clib_calljmp) (x0=function, x1=arg, x2=new_stack)
789  .global cdecl(clib_calljmp)
790  .type cdecl(clib_calljmp), %function
791 cdecl(clib_calljmp):
792  // save fn ptr
793  mov x3, x0
794  // set up fn arg
795  mov x0, x1
796  // switch stacks
797  mov x4, sp
798 
799  // space for saved sp, lr on new stack
800  sub x2, x2, #16
801  mov sp, x2
802 
803  // save old sp and link register on new stack
804  str x4, [sp]
805  str x30,[sp,#8]
806  mov x4, sp
807 
808  // go there
809  blr x3
810 
811  // restore old sp and link register
812  mov x4, sp
813 
814  ldr x3, [x4]
815  ldr x30,[x4, #8]
816  mov sp, x3
817  ret
818  .size cdecl(clib_calljmp), .-cdecl(clib_calljmp)
819 #else
820 #error "unknown machine"
821 #endif
822 
823 #ifndef __APPLE__
824 .section .note.GNU-stack,"",%progbits
825 #endif