Initial commit of vpp code.
[vpp.git] / vppinfra / vppinfra / longjmp.S
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 _prologue (clib_calljmp)
294         /* Make sure stack is 16 byte aligned. */
295         andi. 0, 5, 0xf
296         sub  5, 5, 0
297         addi 5, 5, -16
298         
299         /* Save old stack/link pointer on new stack. */
300         std 1, 0(5)
301         mflr 0
302         std 0, 8(5)
303         
304         /* Switch stacks. */
305         mr 1, 5
306         
307         /* Get function pointer. */
308         ld 0, 0(3)
309         mtctr 0
310         
311         /* Move argument into place. */
312         mr 3, 4
313         
314         /* Away we go. */
315         bctrl
316         
317         /* Switch back to old stack. */
318         ld 0, 8(1)
319         mtlr 0
320         ld 0, 0(1)
321         mr 1, 0
322         
323         /* Return to caller. */
324         blr
325         
326 #elif defined(__powerpc__)
327         
328 #define _foreach_14_31                                                  \
329 _ (14, 0)  _ (15, 1)  _ (16, 2)  _ (17, 3)  _ (18, 4)  _ (19, 5)        \
330 _ (20, 6)  _ (21, 7)  _ (22, 8)  _ (23, 9)  _ (24, 10) _ (25, 11)       \
331 _ (26, 12) _ (27, 13) _ (28, 14) _ (29, 15) _ (30, 16) _ (31, 17)
332
333 #define _foreach_20_31                                          \
334 _ (20, 0) _ (21, 1) _ (22, 2) _ (23, 3) _ (24, 4)  _ (25, 5)    \
335 _ (26, 6) _ (27, 7) _ (28, 8) _ (29, 9) _ (30, 10) _ (31, 11)
336         
337 #ifdef __ALTIVEC__
338 #define CLIB_POWERPC_ALTIVEC_N_REGS 12
339 #else
340 #define CLIB_POWERPC_ALTIVEC_N_REGS 0
341 #endif
342
343         .global clib_setjmp
344         .align 4
345         .type clib_setjmp, @function
346 clib_setjmp:
347         mflr 0
348         stw 0, 4*0(3)
349         stw 1, 4*1(3)
350         mfcr 0
351         stw 0, 4*2(3)
352 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
353         mfspr 0, 256
354 #endif
355         stw 0, 4*3(3)
356         
357 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
358         li 5, 4*4
359 #define _(a,b) stvx a, 3, 5 ; addi 5, 5, 16 ;
360         _foreach_20_31
361 #undef _
362 #endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */
363         
364         /* gp 14 - 31 */
365 #define _(a,b) stw a,  4*(1*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 0*18)(3) ; 
366         _foreach_14_31
367 #undef _
368         
369         /* fp 14 - 31 */
370 #define _(a,b) stfd a, 4*(2*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 1*18)(3) ;
371         _foreach_14_31
372 #undef _
373
374         /* Return value. */
375         mr 3, 4
376         
377         blr
378         
379         .global clib_longjmp
380         .align 4
381         .type clib_longjmp, @function
382 clib_longjmp:   
383         
384         lwz 0, 4*0(3)
385         mtlr 0
386         lwz 1, 4*1(3)
387         lwz 0, 4*2(3)
388         mtcr 0
389         lwz 0, 4*3(3)
390 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
391         mtspr 256, 0
392 #endif
393         
394 #if CLIB_POWERPC_ALTIVEC_N_REGS > 0
395         li 5, 4*4
396 #define _(a,b) lvx a, 3, 5 ; addi 5, 5, 16 ;
397         _foreach_20_31
398 #undef _
399 #endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */
400         
401         /* gp 14 - 31 */
402 #define _(a,b) lwz a, 4*(1*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 0*18)(3) ;
403         _foreach_14_31
404 #undef _
405         
406         /* fp 14 - 31 */
407 #define _(a,b) lfd a, 4*(2*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 1*18)(3) ;
408         _foreach_14_31
409 #undef _
410
411         /* Return value. */
412         mr 3, 4
413         
414         blr
415
416         .global clib_calljmp
417         .align 4
418         .type clib_calljmp, @function
419 clib_calljmp:   
420         /* Make sure stack is 16 byte aligned. */
421         andi. 0, 5, 0xf
422         sub  5, 5, 0
423         addi 5, 5, -16
424         
425         /* Save old stack/link pointer on new stack. */
426         stw 1, 0(5)
427         mflr 0
428         stw 0, 4(5)
429         
430         /* account for (sp, lr) tuple, and keep aligned */
431         addi 5, 5, -16
432         
433         /* Switch stacks. */
434         mr 1, 5
435         
436         /* Move argument into place. */
437         mtctr 3
438         mr 3, 4
439         
440         /* Away we go. */
441         bctrl
442         
443         /* back to our synthetic frame */
444         addi 1,1,16
445         
446         /* Switch back to old stack. */
447         lwz 0, 4(1)
448         mtlr 0
449         lwz 0, 0(1)
450         mr 1, 0
451         
452         /* Return to caller. */
453         blr
454         
455 #elif defined(__arm__)
456         
457         .global clib_setjmp
458         .align 4
459         .type clib_setjmp, %function
460 clib_setjmp:
461         mov ip, r0              /* jmp buffer */
462
463         /* Save integer registers */
464         stmia ip!, {v1-v6, sl, fp, sp, lr}
465         
466 #ifdef __IWMMXT__
467         /* Save the call-preserved iWMMXt registers.  */
468         wstrd wr10, [ip], #8
469         wstrd wr11, [ip], #8
470         wstrd wr12, [ip], #8
471         wstrd wr13, [ip], #8
472         wstrd wr14, [ip], #8
473         wstrd wr15, [ip], #8
474 #endif
475
476         /* Give back user's return value. */
477         mov r1, r0
478         bx lr
479         
480         .global clib_longjmp
481         .align 4
482         .type clib_longjmp, %function
483 clib_longjmp:   
484         mov ip, r0              /* jmp buffer */
485
486         /* Restore integer registers. */
487         ldmia     ip!,  {v1-v6, sl, fp, sp, lr}
488         
489 #ifdef __IWMMXT__
490         /* Save the call-preserved iWMMXt registers.  */
491         wldrd wr10, [ip], #8
492         wldrd wr11, [ip], #8
493         wldrd wr12, [ip], #8
494         wldrd wr13, [ip], #8
495         wldrd wr14, [ip], #8
496         wldrd wr15, [ip], #8
497 #endif
498         
499         /* Give back user's return value. */
500         mov r1, r0
501         bx lr
502
503         .global clib_calljmp
504         .align 4
505         .type clib_calljmp, %function
506 clib_calljmp:   
507         /* Make sure stack is 8 byte aligned. */
508         bic r2, r2, #7
509         
510         /* Allocate space for stack/link pointer on new stack. */
511         sub r2, r2, #8  
512         
513         /* Save old stack/link pointer on new stack. */
514         str sp, [r2, #0]
515         str lr, [r2, #4]
516         
517         /* Switch stacks. */
518         mov sp, r2
519         
520         /* Save function to call. */
521         mov ip, r0
522         
523         /* Move argument into place. */
524         mov r0, r1
525         
526         /* Away we go. */
527         bx ip
528         
529         /* Switch back to old stack. */
530         ldr lr, [sp, #4]
531         ldr ip, [sp, #0]
532         mov sp, ip
533         
534         /* Return to caller. */
535         bx lr
536         
537 #elif defined(__xtensa__)
538         
539         /* FIXME implement if needed. */
540         .global clib_setjmp
541         .align 4
542         .type clib_setjmp, %function
543 clib_setjmp:
544 1:      j 1b
545
546         .global clib_longjmp
547         .align 4
548         .type clib_longjmp, @function
549 clib_longjmp:   
550 1:      j 1b
551         
552         .global clib_calljmp
553         .align 4
554         .type clib_calljmp, %function
555 clib_calljmp:   
556 1:      j 1b
557         
558 #elif defined(__TMS320C6X__)
559         
560         /* FIXME implement if needed. */
561         .global clib_setjmp
562         .align 4
563         .type clib_setjmp, %function
564 clib_setjmp:
565 1:      B       .S1     1b
566
567         .global clib_longjmp
568         .align 4
569         .type clib_longjmp, @function
570 clib_longjmp:   
571 1:      B       .S1     1b
572         
573         .global clib_calljmp
574         .align 4
575         .type clib_calljmp, %function
576 clib_calljmp:   
577 1:      B       .S1     1b
578         
579 #else
580 #error "unknown machine"
581 #endif  
582
583 .section .note.GNU-stack,"",%progbits