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__)
214 #define _prologue(n) \
217 .section ".opd", "aw" ; \
219 n: .quad .##n, .TOC.@tocbase, 0 ; \
222 .type .##n, @function ; \
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)
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)
235 #define CLIB_POWERPC_ALTIVEC_N_REGS 12
237 #define CLIB_POWERPC_ALTIVEC_N_REGS 0
240 _prologue (cdecl(clib_setjmp))
251 #define _(a,b) std a, 8*((b) + 4 + 18*0)(3) ;
256 #define _(a,b) stfd a, 8*((b) + 4 + 18*1)(3) ;
260 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
263 #define _(a,b) stvx a, 5, 3 ; addi 5, 5, 16 ;
266 #endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */
273 _prologue (cdecl(clib_longjmp))
284 #define _(a,b) ld a, 8*((b) + 4 + 18*0)(3) ;
289 #define _(a,b) lfd a, 8*((b) + 4 + 18*1)(3) ;
293 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
296 #define _(a,b) lvx a, 5, 3 ; addi 5, 5, 16 ;
299 #endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */
306 .globl cdecl(clib_calljmp)
310 .quad .L.cdecl(clib_calljmp),.TOC.@tocbase,0
312 .type cdecl(clib_calljmp), @function
313 .L.cdecl(clib_calljmp):
340 .byte 0,0,0,1,128,0,0,0
341 .size cdecl(clib_calljmp),.-.L.cdecl(clib_calljmp)
343 #elif defined(__powerpc__)
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)
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)
355 #define CLIB_POWERPC_ALTIVEC_N_REGS 12
357 #define CLIB_POWERPC_ALTIVEC_N_REGS 0
360 .global cdecl(clib_setjmp)
362 .type cdecl(clib_setjmp), @function
369 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
374 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
376 #define _(a,b) stvx a, 3, 5 ; addi 5, 5, 16 ;
379 #endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */
382 #define _(a,b) stw a, 4*(1*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 0*18)(3) ;
387 #define _(a,b) stfd a, 4*(2*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 1*18)(3) ;
396 .global cdecl(clib_longjmp)
398 .type cdecl(clib_longjmp), @function
407 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
411 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
413 #define _(a,b) lvx a, 3, 5 ; addi 5, 5, 16 ;
416 #endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */
419 #define _(a,b) lwz a, 4*(1*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 0*18)(3) ;
424 #define _(a,b) lfd a, 4*(2*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 1*18)(3) ;
433 .global cdecl(clib_calljmp)
435 .type cdecl(clib_calljmp), @function
437 /* Make sure stack is 16 byte aligned. */
442 /* Save old stack/link pointer on new stack. */
447 /* account for (sp, lr) tuple, and keep aligned */
453 /* Move argument into place. */
460 /* back to our synthetic frame */
463 /* Switch back to old stack. */
469 /* Return to caller. */
472 #elif defined(__arm__)
474 .global cdecl(clib_setjmp)
476 .type cdecl(clib_setjmp), %function
478 mov ip, r0 /* jmp buffer */
480 /* Save integer registers */
481 stmia ip!, {v1-v6, sl, fp, sp, lr}
484 /* Save the call-preserved iWMMXt registers. */
493 /* Give back user's return value. */
497 .global cdecl(clib_longjmp)
499 .type cdecl(clib_longjmp), %function
501 mov ip, r0 /* jmp buffer */
503 /* Restore integer registers. */
504 ldmia ip!, {v1-v6, sl, fp, sp, lr}
507 /* Save the call-preserved iWMMXt registers. */
516 /* Give back user's return value. */
520 .global cdecl(clib_calljmp)
522 .type cdecl(clib_calljmp), %function
524 /* Make sure stack is 8 byte aligned. */
527 /* Allocate space for stack/link pointer on new stack. */
530 /* Save old stack/link pointer on new stack. */
537 /* Save function to call. */
540 /* Move argument into place. */
546 /* Switch back to old stack. */
551 /* Return to caller. */
554 #elif defined(__xtensa__)
556 /* FIXME implement if needed. */
557 .global cdecl(clib_setjmp)
559 .type cdecl(clib_setjmp), %function
563 .global cdecl(clib_longjmp)
565 .type cdecl(clib_longjmp), @function
569 .global cdecl(clib_calljmp)
571 .type cdecl(clib_calljmp), %function
575 #elif defined(__TMS320C6X__)
577 /* FIXME implement if needed. */
578 .global cdecl(clib_setjmp)
580 .type cdecl(clib_setjmp), %function
584 .global cdecl(clib_longjmp)
586 .type cdecl(clib_longjmp), @function
590 .global cdecl(clib_calljmp)
592 .type cdecl(clib_calljmp), %function
596 #elif defined(_mips) && __mips == 64
598 .global cdecl(clib_setjmp)
600 .type cdecl(clib_setjmp), %function
618 .global cdecl(clib_longjmp)
620 .type cdecl(clib_longjmp), @function
642 .global cdecl(clib_calljmp)
644 .type cdecl(clib_calljmp), %function
646 /* Force 16 byte alignment of the new stack */
649 /* Save old ra/gp/sp on new stack */
650 daddiu $t0, $t0, (-24)
661 /* Switch back to old ra/gp/sp */
666 /* Return to caller */
670 #elif defined (__aarch64__)
672 Copyright (c) 2011, 2012 ARM Ltd
674 Redistribution and use in source and binary forms, with or without
675 modification, are permitted provided that the following conditions
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
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.
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); \
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
714 #define REG_PAIR(REG1, REG2, OFFS) stp REG1, REG2, [x0, OFFS]
715 #define REG_ONE(REG1, OFFS) str REG1, [x0, OFFS]
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
727 #define REG_PAIR(REG1, REG2, OFFS) ldp REG1, REG2, [x0, OFFS]
728 #define REG_ONE(REG1, OFFS) ldr REG1, [x0, OFFS]
737 // use br not ret, as ret is guaranteed to mispredict
739 .size cdecl(clib_longjmp), .-cdecl(clib_longjmp)
742 // void cdecl(clib_calljmp) (x0=function, x1=arg, x2=new_stack)
743 .global cdecl(clib_calljmp)
744 .type cdecl(clib_calljmp), %function
753 // space for saved sp, lr on new stack
757 // save old sp and link register on new stack
765 // restore old sp and link register
772 .size cdecl(clib_calljmp), .-cdecl(clib_calljmp)
774 #error "unknown machine"
778 .section .note.GNU-stack,"",%progbits