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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 Copyright (c) 2005 Eliot Dresselhaus
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:
26 The above copyright notice and this permission notice shall be
27 included in all copies or substantial portions of the Software.
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.
38 #if defined(__APPLE__)
39 # define cdecl(s) _##s
44 #if defined(__x86_64__)
45 .global cdecl(clib_setjmp)
48 .type cdecl(clib_setjmp), @function
59 /* Save SP after return. */
63 /* Save PC we are returning to from stack frame. */
67 /* Give back user's return value. */
71 .global cdecl(clib_longjmp)
74 .type cdecl(clib_longjmp), @function
87 /* Give back user's return value. */
93 .global cdecl(clib_calljmp)
96 .type cdecl(clib_calljmp), @function
99 /* Make sure stack is 16-byte aligned. */
104 /* Get return address. */
107 /* Switch to new stack. */
110 /* Save return address on new stack. */
113 /* Save old stack pointer on new stack. */
119 /* Move argument into place. */
125 /* Switch back to old stack. */
130 /* Return to caller. */
134 .global cdecl(clib_setjmp)
136 .type cdecl(clib_setjmp), @function
145 /* Save SP after return. */
149 /* Save PC we are returning to from stack frame. */
153 /* Give back user's return value. */
157 .global cdecl(clib_longjmp)
159 .type cdecl(clib_longjmp), @function
163 /* Give back user's return value. */
177 .global cdecl(clib_calljmp)
179 .type cdecl(clib_calljmp), @function
181 /* Get new stack pointer. */
187 /* Save old stack pointer on new stack. */
191 /* Put function argument in stack frame. */
201 /* Switch back to old stack. */
205 /* Return to caller. */
208 #elif defined(__SPU__)
210 #elif defined(__powerpc64__)
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)
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)
222 #define CLIB_POWERPC_ALTIVEC_N_REGS 12
224 #define CLIB_POWERPC_ALTIVEC_N_REGS 0
229 #define _prologue(n) \
232 .type n, @function ; \
236 #define _gep_lep(n) \
238 addis 2, 12, .TOC.-.L##n##_gep@ha ; \
239 addi 2, 2, .TOC.-.L##n##_gep@l ; \
241 .localentry n, .L##n##_lep-.L##n##_gep
243 #else /* _CALL_ELF == 1 */
245 #define _prologue(n) \
248 .type .##n, @function ; \
249 .section ".opd", "aw" ,@progbits ; \
252 .quad .L##n##_begin ; \
253 .quad .TOC.@tocbase ; \
260 #define _epilogue(n) \
264 .size n, .L##n##_end-.L##n##_begin
273 _prologue(clib_setjmp)
284 #define _(a,b) std a, 8*((b) + 4 + 18*0)(3) ;
289 #define _(a,b) stfd a, 8*((b) + 4 + 18*1)(3) ;
293 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
296 #define _(a,b) stvx a, 5, 3 ; addi 5, 5, 16 ;
299 #endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */
304 _epilogue(clib_setjmp)
306 _prologue(clib_longjmp)
317 #define _(a,b) ld a, 8*((b) + 4 + 18*0)(3) ;
322 #define _(a,b) lfd a, 8*((b) + 4 + 18*1)(3) ;
326 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
329 #define _(a,b) lvx a, 5, 3 ; addi 5, 5, 16 ;
332 #endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */
337 _epilogue(clib_longjmp)
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 */
360 _epilogue(clib_calljmp)
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 */
373 std 2,40(1) /* store TOC pointer into the stack */
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 */
386 _epilogue(clib_calljmp)
389 #elif defined(__powerpc__)
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)
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)
401 #define CLIB_POWERPC_ALTIVEC_N_REGS 12
403 #define CLIB_POWERPC_ALTIVEC_N_REGS 0
406 .global cdecl(clib_setjmp)
408 .type cdecl(clib_setjmp), @function
415 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
420 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
422 #define _(a,b) stvx a, 3, 5 ; addi 5, 5, 16 ;
425 #endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */
428 #define _(a,b) stw a, 4*(1*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 0*18)(3) ;
433 #define _(a,b) stfd a, 4*(2*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 1*18)(3) ;
442 .global cdecl(clib_longjmp)
444 .type cdecl(clib_longjmp), @function
453 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
457 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
459 #define _(a,b) lvx a, 3, 5 ; addi 5, 5, 16 ;
462 #endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */
465 #define _(a,b) lwz a, 4*(1*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 0*18)(3) ;
470 #define _(a,b) lfd a, 4*(2*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 1*18)(3) ;
479 .global cdecl(clib_calljmp)
481 .type cdecl(clib_calljmp), @function
483 /* Make sure stack is 16 byte aligned. */
488 /* Save old stack/link pointer on new stack. */
493 /* account for (sp, lr) tuple, and keep aligned */
499 /* Move argument into place. */
506 /* back to our synthetic frame */
509 /* Switch back to old stack. */
515 /* Return to caller. */
518 #elif defined(__arm__)
520 .global cdecl(clib_setjmp)
522 .type cdecl(clib_setjmp), %function
524 mov ip, r0 /* jmp buffer */
526 /* Save integer registers */
527 stmia ip!, {v1-v6, sl, fp, sp, lr}
530 /* Save the call-preserved iWMMXt registers. */
539 /* Give back user's return value. */
543 .global cdecl(clib_longjmp)
545 .type cdecl(clib_longjmp), %function
547 mov ip, r0 /* jmp buffer */
549 /* Restore integer registers. */
550 ldmia ip!, {v1-v6, sl, fp, sp, lr}
553 /* Save the call-preserved iWMMXt registers. */
562 /* Give back user's return value. */
566 .global cdecl(clib_calljmp)
568 .type cdecl(clib_calljmp), %function
570 /* Make sure stack is 8 byte aligned. */
573 /* Allocate space for stack/link pointer on new stack. */
576 /* Save old stack/link pointer on new stack. */
583 /* Save function to call. */
586 /* Move argument into place. */
592 /* Switch back to old stack. */
597 /* Return to caller. */
600 #elif defined(__xtensa__)
602 /* FIXME implement if needed. */
603 .global cdecl(clib_setjmp)
605 .type cdecl(clib_setjmp), %function
609 .global cdecl(clib_longjmp)
611 .type cdecl(clib_longjmp), @function
615 .global cdecl(clib_calljmp)
617 .type cdecl(clib_calljmp), %function
621 #elif defined(__TMS320C6X__)
623 /* FIXME implement if needed. */
624 .global cdecl(clib_setjmp)
626 .type cdecl(clib_setjmp), %function
630 .global cdecl(clib_longjmp)
632 .type cdecl(clib_longjmp), @function
636 .global cdecl(clib_calljmp)
638 .type cdecl(clib_calljmp), %function
642 #elif defined(_mips) && __mips == 64
644 .global cdecl(clib_setjmp)
646 .type cdecl(clib_setjmp), %function
664 .global cdecl(clib_longjmp)
666 .type cdecl(clib_longjmp), @function
688 .global cdecl(clib_calljmp)
690 .type cdecl(clib_calljmp), %function
692 /* Force 16 byte alignment of the new stack */
695 /* Save old ra/gp/sp on new stack */
696 daddiu $t0, $t0, (-24)
707 /* Switch back to old ra/gp/sp */
712 /* Return to caller */
716 #elif defined (__aarch64__)
718 Copyright (c) 2011, 2012 ARM Ltd
720 Redistribution and use in source and binary forms, with or without
721 modification, are permitted provided that the following conditions
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
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.
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); \
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
760 #define REG_PAIR(REG1, REG2, OFFS) stp REG1, REG2, [x0, OFFS]
761 #define REG_ONE(REG1, OFFS) str REG1, [x0, OFFS]
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
773 #define REG_PAIR(REG1, REG2, OFFS) ldp REG1, REG2, [x0, OFFS]
774 #define REG_ONE(REG1, OFFS) ldr REG1, [x0, OFFS]
783 // use br not ret, as ret is guaranteed to mispredict
785 .size cdecl(clib_longjmp), .-cdecl(clib_longjmp)
788 // void cdecl(clib_calljmp) (x0=function, x1=arg, x2=new_stack)
789 .global cdecl(clib_calljmp)
790 .type cdecl(clib_calljmp), %function
799 // space for saved sp, lr on new stack
803 // save old sp and link register on new stack
811 // restore old sp and link register
818 .size cdecl(clib_calljmp), .-cdecl(clib_calljmp)
820 #error "unknown machine"
824 .section .note.GNU-stack,"",%progbits