FD.io VPP  v16.06
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(__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 (__aarch64__)
584 /*
585  Copyright (c) 2011, 2012 ARM Ltd
586  All rights reserved.
587  Redistribution and use in source and binary forms, with or without
588  modification, are permitted provided that the following conditions
589  are met:
590  1. Redistributions of source code must retain the above copyright
591  notice, this list of conditions and the following disclaimer.
592  2. Redistributions in binary form must reproduce the above copyright
593  notice, this list of conditions and the following disclaimer in the
594  documentation and/or other materials provided with the distribution.
595  3. The name of the company may not be used to endorse or promote
596  products derived from this software without specific prior written
597  permission.
598  THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
599  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
600  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
601  IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
602  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
603  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
604  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
605  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
606  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
607  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
608  */
609 #define GPR_LAYOUT \
610  REG_PAIR (x19, x20, 0); \
611  REG_PAIR (x21, x22, 16); \
612  REG_PAIR (x23, x24, 32); \
613  REG_PAIR (x25, x26, 48); \
614  REG_PAIR (x27, x28, 64); \
615  REG_PAIR (x29, x30, 80); \
616  REG_ONE (x16, 96)
617 #define FPR_LAYOUT \
618  REG_PAIR ( d8, d9, 112); \
619  REG_PAIR (d10, d11, 128); \
620  REG_PAIR (d12, d13, 144); \
621  REG_PAIR (d14, d15, 160);
622 // int clib_setjmp (jmp_buf)
623  .global clib_setjmp
624  .type clib_setjmp, %function
625 clib_setjmp:
626  mov x16, sp
627 #define REG_PAIR(REG1, REG2, OFFS) stp REG1, REG2, [x0, OFFS]
628 #define REG_ONE(REG1, OFFS) str REG1, [x0, OFFS]
629  GPR_LAYOUT
630  FPR_LAYOUT
631 #undef REG_PAIR
632 #undef REG_ONE
633  mov x0, x1
634  ret
635  .size clib_setjmp, .-clib_setjmp
636 // void clib_longjmp (jmp_buf, int) __attribute__ ((noreturn))
637  .global clib_longjmp
638  .type clib_longjmp, %function
639 clib_longjmp:
640 #define REG_PAIR(REG1, REG2, OFFS) ldp REG1, REG2, [x0, OFFS]
641 #define REG_ONE(REG1, OFFS) ldr REG1, [x0, OFFS]
642  GPR_LAYOUT
643  FPR_LAYOUT
644 #undef REG_PAIR
645 #undef REG_ONE
646  mov sp, x16
647  mov x0, x1
648  // cmp w1, #0
649  // cinc w0, w1, eq
650  // use br not ret, as ret is guaranteed to mispredict
651  br x30
652  .size clib_longjmp, .-clib_longjmp
653 
654 
655 // void clib_calljmp (x0=function, x1=arg, x2=new_stack)
656  .global clib_calljmp
657  .type clib_calljmp, %function
658 clib_calljmp:
659  // save fn ptr
660  mov x3, x0
661  // set up fn arg
662  mov x0, x1
663  // switch stacks
664  mov x4, sp
665 
666  // space for saved sp, lr on new stack
667  sub x2, x2, #16
668  mov sp, x2
669 
670  // save old sp and link register on new stack
671  str x4, [sp]
672  str x30,[sp,#8]
673  mov x4, sp
674 
675  // go there
676  blr x3
677 
678  // restore old sp and link register
679  mov x4, sp
680 
681  ldr x3, [x4]
682  ldr x30,[x4, #8]
683  mov sp, x3
684  ret
685  .size clib_calljmp, .-clib_calljmp
686 #else
687 #error "unknown machine"
688 #endif
689 
690 .section .note.GNU-stack,"",%progbits