blob: d4dd4c7d916322aa3cc021ab11273e9a655b7678 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
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
42clib_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
65clib_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
85clib_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
124clib_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
147clib_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
167clib_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 ; \
206n: .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
Dave Barachbfdedbd2016-01-20 09:11:55 -0500293 .globl clib_calljmp
294 .section ".opd","aw"
295 .align 3
296clib_calljmp:
297 .quad .L.clib_calljmp,.TOC.@tocbase,0
298 .previous
299 .type clib_calljmp, @function
300.L.clib_calljmp:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700301 mflr 0
Dave Barachbfdedbd2016-01-20 09:11:55 -0500302 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)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700316 bctrl
Dave Barachbfdedbd2016-01-20 09:11:55 -0500317 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)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700324 mtlr 0
Ed Warnickecb9cada2015-12-08 15:45:58 -0700325 blr
Dave Barachbfdedbd2016-01-20 09:11:55 -0500326 .long 0
327 .byte 0,0,0,1,128,0,0,0
328 .size clib_calljmp,.-.L.clib_calljmp
Ed Warnickecb9cada2015-12-08 15:45:58 -0700329
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
350clib_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
386clib_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
423clib_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
464clib_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. */
Christophe Fontainefef15b42016-04-09 12:38:49 +0900481 mov r0, r1
Ed Warnickecb9cada2015-12-08 15:45:58 -0700482 bx lr
483
484 .global clib_longjmp
485 .align 4
486 .type clib_longjmp, %function
487clib_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. */
Christophe Fontainefef15b42016-04-09 12:38:49 +0900504 mov r0, r1
Ed Warnickecb9cada2015-12-08 15:45:58 -0700505 bx lr
506
507 .global clib_calljmp
508 .align 4
509 .type clib_calljmp, %function
510clib_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
547clib_setjmp:
5481: j 1b
549
550 .global clib_longjmp
551 .align 4
552 .type clib_longjmp, @function
553clib_longjmp:
5541: j 1b
555
556 .global clib_calljmp
557 .align 4
558 .type clib_calljmp, %function
559clib_calljmp:
5601: 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
568clib_setjmp:
5691: B .S1 1b
570
571 .global clib_longjmp
572 .align 4
573 .type clib_longjmp, @function
574clib_longjmp:
5751: B .S1 1b
576
577 .global clib_calljmp
578 .align 4
579 .type clib_calljmp, %function
580clib_calljmp:
5811: B .S1 1b
582
Dave Barach61efa142016-01-22 08:23:09 -0500583#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
625clib_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
639clib_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
658clib_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
Ed Warnickecb9cada2015-12-08 15:45:58 -0700686#else
687#error "unknown machine"
688#endif
689
690.section .note.GNU-stack,"",%progbits