Type: improvement Change-Id: Iea8e08dc18b72334f69af77c2753e900be6b97fb Signed-off-by: Damjan Marion <damarion@cisco.com>
826 lines
18 KiB
ArmAsm
826 lines
18 KiB
ArmAsm
/*
|
|
* Copyright (c) 2015 Cisco and/or its affiliates.
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at:
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
/*
|
|
Copyright (c) 2005 Eliot Dresselhaus
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
a copy of this software and associated documentation files (the
|
|
"Software"), to deal in the Software without restriction, including
|
|
without limitation the rights to use, copy, modify, merge, publish,
|
|
distribute, sublicense, and/or sell copies of the Software, and to
|
|
permit persons to whom the Software is furnished to do so, subject to
|
|
the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be
|
|
included in all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
#if defined(__APPLE__)
|
|
# define cdecl(s) _##s
|
|
#else
|
|
# define cdecl(s) s
|
|
#endif
|
|
|
|
#if defined(__x86_64__)
|
|
.global cdecl(clib_setjmp)
|
|
.align 4
|
|
#ifndef __APPLE__
|
|
.type cdecl(clib_setjmp), @function
|
|
#endif
|
|
|
|
cdecl(clib_setjmp):
|
|
movq %rbx, 8*0(%rdi)
|
|
movq %rbp, 8*1(%rdi)
|
|
movq %r12, 8*2(%rdi)
|
|
movq %r13, 8*3(%rdi)
|
|
movq %r14, 8*4(%rdi)
|
|
movq %r15, 8*5(%rdi)
|
|
|
|
/* Save SP after return. */
|
|
leaq 8(%rsp), %rdx
|
|
movq %rdx, 8*6(%rdi)
|
|
|
|
/* Save PC we are returning to from stack frame. */
|
|
movq 0(%rsp), %rax
|
|
movq %rax, 8*7(%rdi)
|
|
|
|
/* Give back user's return value. */
|
|
movq %rsi, %rax
|
|
ret
|
|
|
|
.global cdecl(clib_longjmp)
|
|
.align 4
|
|
#ifndef __APPLE__
|
|
.type cdecl(clib_longjmp), @function
|
|
#endif
|
|
cdecl(clib_longjmp):
|
|
/* Restore regs. */
|
|
movq 8*0(%rdi), %rbx
|
|
movq 8*1(%rdi), %rbp
|
|
movq 8*2(%rdi), %r12
|
|
movq 8*3(%rdi), %r13
|
|
movq 8*4(%rdi), %r14
|
|
movq 8*5(%rdi), %r15
|
|
movq 8*6(%rdi), %rsp
|
|
movq 8*7(%rdi), %rdx
|
|
|
|
/* Give back user's return value. */
|
|
movq %rsi, %rax
|
|
|
|
/* Away we go. */
|
|
jmpq *%rdx
|
|
|
|
.global cdecl(clib_calljmp)
|
|
.align 4
|
|
#ifndef __APPLE__
|
|
.type cdecl(clib_calljmp), @function
|
|
#endif
|
|
cdecl(clib_calljmp):
|
|
/* Make sure stack is 16-byte aligned. */
|
|
movq %rdx, %rax
|
|
andq $0xf, %rax
|
|
subq %rax, %rdx
|
|
|
|
/* Get return address. */
|
|
pop %rax
|
|
|
|
/* Switch to new stack. */
|
|
xchgq %rsp, %rdx
|
|
|
|
/* Save return address on new stack. */
|
|
push %rax
|
|
|
|
/* Save old stack pointer on new stack. */
|
|
push %rdx
|
|
|
|
/* Get function. */
|
|
movq %rdi, %rdx
|
|
|
|
/* Move argument into place. */
|
|
movq %rsi, %rdi
|
|
|
|
/* Away we go. */
|
|
callq *%rdx
|
|
|
|
/* Switch back to old stack. */
|
|
movq 8(%rsp), %rdx
|
|
movq 0(%rsp), %rcx
|
|
xchgq %rcx, %rsp
|
|
|
|
/* Return to caller. */
|
|
jmpq *%rdx
|
|
|
|
#elif defined(i386)
|
|
.global cdecl(clib_setjmp)
|
|
.align 4
|
|
.type cdecl(clib_setjmp), @function
|
|
cdecl(clib_setjmp):
|
|
movl 4(%esp), %ecx
|
|
|
|
movl %ebp, 4*0(%ecx)
|
|
movl %ebx, 4*1(%ecx)
|
|
movl %edi, 4*2(%ecx)
|
|
movl %esi, 4*3(%ecx)
|
|
|
|
/* Save SP after return. */
|
|
leal 4(%esp), %edx
|
|
movl %edx, 4*4(%ecx)
|
|
|
|
/* Save PC we are returning to from stack frame. */
|
|
movl 0(%esp), %eax
|
|
movl %eax, 4*5(%ecx)
|
|
|
|
/* Give back user's return value. */
|
|
movl 8(%esp), %eax
|
|
ret
|
|
|
|
.global cdecl(clib_longjmp)
|
|
.align 4
|
|
.type cdecl(clib_longjmp), @function
|
|
cdecl(clib_longjmp):
|
|
movl 4(%esp), %ecx
|
|
|
|
/* Give back user's return value. */
|
|
movl 8(%esp), %eax
|
|
|
|
/* Restore regs. */
|
|
movl 4*0(%ecx), %ebp
|
|
movl 4*1(%ecx), %ebx
|
|
movl 4*2(%ecx), %edi
|
|
movl 4*3(%ecx), %esi
|
|
movl 4*4(%ecx), %esp
|
|
movl 4*5(%ecx), %edx
|
|
|
|
/* Away we go. */
|
|
jmp *%edx
|
|
|
|
.global cdecl(clib_calljmp)
|
|
.align 4
|
|
.type cdecl(clib_calljmp), @function
|
|
cdecl(clib_calljmp):
|
|
/* Get new stack pointer. */
|
|
movl 12(%esp), %edx
|
|
|
|
/* Switch stacks. */
|
|
xchgl %esp, %edx
|
|
|
|
/* Save old stack pointer on new stack. */
|
|
sub $8, %esp
|
|
movl %edx, 4(%esp)
|
|
|
|
/* Put function argument in stack frame. */
|
|
movl 8(%edx), %eax
|
|
movl %eax, 0(%esp)
|
|
|
|
/* Get function. */
|
|
movl 4(%edx), %eax
|
|
|
|
/* Away we go. */
|
|
call *%eax
|
|
|
|
/* Switch back to old stack. */
|
|
movl 4(%esp), %edx
|
|
xchgl %edx, %esp
|
|
|
|
/* Return to caller. */
|
|
ret
|
|
|
|
#elif defined(__SPU__)
|
|
|
|
#elif defined(__powerpc64__)
|
|
|
|
#define _foreach_14_31 \
|
|
_ (14, 0) _ (15, 1) _ (16, 2) _ (17, 3) _ (18, 4) _ (19, 5) \
|
|
_ (20, 6) _ (21, 7) _ (22, 8) _ (23, 9) _ (24, 10) _ (25, 11) \
|
|
_ (26, 12) _ (27, 13) _ (28, 14) _ (29, 15) _ (30, 16) _ (31, 17)
|
|
|
|
#define _foreach_20_31 \
|
|
_ (20, 0) _ (21, 1) _ (22, 2) _ (23, 3) _ (24, 4) _ (25, 5) \
|
|
_ (26, 6) _ (27, 7) _ (28, 8) _ (29, 9) _ (30, 10) _ (31, 11)
|
|
|
|
#ifdef __ALTIVEC__
|
|
#define CLIB_POWERPC_ALTIVEC_N_REGS 12
|
|
#else
|
|
#define CLIB_POWERPC_ALTIVEC_N_REGS 0
|
|
#endif
|
|
|
|
#if _CALL_ELF == 2
|
|
|
|
#define _prologue(n) \
|
|
.globl n ; \
|
|
.p2align 4 ; \
|
|
.type n, @function ; \
|
|
n: ; \
|
|
.L##n##_begin: ;
|
|
|
|
#define _gep_lep(n) \
|
|
.L##n##_gep: ; \
|
|
addis 2, 12, .TOC.-.L##n##_gep@ha ; \
|
|
addi 2, 2, .TOC.-.L##n##_gep@l ; \
|
|
.L##n##_lep: ; \
|
|
.localentry n, .L##n##_lep-.L##n##_gep
|
|
|
|
#else /* _CALL_ELF == 1 */
|
|
|
|
#define _prologue(n) \
|
|
.globl n ; \
|
|
.p2align 4 ; \
|
|
.type .##n, @function ; \
|
|
.section ".opd", "aw" ,@progbits ; \
|
|
n: ; \
|
|
.p2align 3 ; \
|
|
.quad .L##n##_begin ; \
|
|
.quad .TOC.@tocbase ; \
|
|
.quad 0 ; \
|
|
.text ; \
|
|
.L##n##_begin: ;
|
|
|
|
#endif
|
|
|
|
#define _epilogue(n) \
|
|
.long 0 ; \
|
|
.quad 0 ; \
|
|
.L##n##_end: ; \
|
|
.size n, .L##n##_end-.L##n##_begin
|
|
|
|
#if _CALL_ELF == 2
|
|
.abiversion 2
|
|
.section ".text"
|
|
#else
|
|
.text
|
|
#endif
|
|
|
|
_prologue(clib_setjmp)
|
|
mflr 0
|
|
std 0, 8*0(3)
|
|
std 1, 8*1(3)
|
|
std 2, 8*2(3)
|
|
mfcr 0
|
|
std 0, 8*3(3)
|
|
mfspr 0, 256
|
|
stw 0, 8*4(3)
|
|
|
|
/* gprs 14 - 31 */
|
|
#define _(a,b) std a, 8*((b) + 4 + 18*0)(3) ;
|
|
_foreach_14_31
|
|
#undef _
|
|
|
|
/* fprs 14 - 31 */
|
|
#define _(a,b) stfd a, 8*((b) + 4 + 18*1)(3) ;
|
|
_foreach_14_31
|
|
#undef _
|
|
|
|
#if CLIB_POWERPC_ALTIVEC_N_REGS > 0
|
|
/* vrs 20 - 31 */
|
|
li 5, 8*(4 + 18*2)
|
|
#define _(a,b) stvx a, 5, 3 ; addi 5, 5, 16 ;
|
|
_foreach_20_31
|
|
#undef _
|
|
#endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */
|
|
|
|
/* Return value. */
|
|
mr 3, 4
|
|
blr
|
|
_epilogue(clib_setjmp)
|
|
|
|
_prologue(clib_longjmp)
|
|
ld 0, 8*0(3)
|
|
mtlr 0
|
|
ld 1, 8*1(3)
|
|
ld 2, 8*2(3)
|
|
ld 0, 8*3(3)
|
|
mtcrf 0xff, 0
|
|
lwz 0, 8*3(3)
|
|
mtspr 256, 0
|
|
|
|
/* gprs 14 - 31 */
|
|
#define _(a,b) ld a, 8*((b) + 4 + 18*0)(3) ;
|
|
_foreach_14_31
|
|
#undef _
|
|
|
|
/* fprs 14 - 31 */
|
|
#define _(a,b) lfd a, 8*((b) + 4 + 18*1)(3) ;
|
|
_foreach_14_31
|
|
#undef _
|
|
|
|
#if CLIB_POWERPC_ALTIVEC_N_REGS > 0
|
|
/* vrs 20 - 31 */
|
|
li 5, 8*(4 + 18*2)
|
|
#define _(a,b) lvx a, 5, 3 ; addi 5, 5, 16 ;
|
|
_foreach_20_31
|
|
#undef _
|
|
#endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */
|
|
|
|
/* Return value. */
|
|
mr 3, 4
|
|
blr
|
|
_epilogue(clib_longjmp)
|
|
|
|
#if _CALL_ELF == 2
|
|
_prologue(clib_calljmp)
|
|
_gep_lep(clib_calljmp)
|
|
mflr 0 /* get link register into r0 */
|
|
std 0,16(1) /* store r0 into the stack frame */
|
|
stdu 1,-32(1) /* move sp down for one frame */
|
|
mr 12,3 /* move func pointer to r12 */
|
|
mr 3,4 /* pass func_arg as first arg */
|
|
std 1,-8(5) /* store old sp into the top of the new stack */
|
|
addi 5,5,-256 /* stack_addr =- 256 */
|
|
mr 1,5 /* set new sp */
|
|
mtctr 12 /* put function pointer into CTR register */
|
|
std 2,24(1) /* store TOC pointer into stack frame */
|
|
bctrl /* unconditional branch to counter register */
|
|
ld 2,24(1) /* load TOC pointer from stack frame */
|
|
addi 1,1,256 /* go back to the start of the new stack */
|
|
ld 1,-8(1) /* load old sp */
|
|
addi 1,1,32 /* move sp back to previous frame */
|
|
ld 0,16(1) /* get old link reg value from the stack */
|
|
mtlr 0 /* restore link reg value */
|
|
blr
|
|
_epilogue(clib_calljmp)
|
|
|
|
#else /* v1 ABI */
|
|
|
|
_prologue(clib_calljmp)
|
|
mflr 0 /* get link register into r0 */
|
|
mr 9,3 /* store function pointer into the r9 */
|
|
std 0,16(1) /* store r0 into the stack frame */
|
|
stdu 1,-112(1) /* move sp down for one frame */
|
|
std 1,-8(5) /* store old sp into the top of the new stack */
|
|
addi 5,5,-256 /* stack_addr =- 256 */
|
|
mr 1,5 /* set new sp */
|
|
ld 10,0(9)
|
|
std 2,40(1) /* store TOC pointer into the stack */
|
|
mr 3,4
|
|
mtctr 10
|
|
ld 11,16(9)
|
|
ld 2,8(9)
|
|
bctrl /* unconditional branch to counter register */
|
|
ld 2,40(1) /* load TOC pointer from the stack */
|
|
addi 1,1,256 /* go back to the start of the new stack */
|
|
ld 1,-8(1) /* load the old sp */
|
|
addi 1,1,112 /* move sp back to previous frame */
|
|
ld 0,16(1) /* restore link register from the stack frame */
|
|
mtlr 0
|
|
blr
|
|
_epilogue(clib_calljmp)
|
|
|
|
#endif
|
|
#elif defined(__powerpc__)
|
|
|
|
#define _foreach_14_31 \
|
|
_ (14, 0) _ (15, 1) _ (16, 2) _ (17, 3) _ (18, 4) _ (19, 5) \
|
|
_ (20, 6) _ (21, 7) _ (22, 8) _ (23, 9) _ (24, 10) _ (25, 11) \
|
|
_ (26, 12) _ (27, 13) _ (28, 14) _ (29, 15) _ (30, 16) _ (31, 17)
|
|
|
|
#define _foreach_20_31 \
|
|
_ (20, 0) _ (21, 1) _ (22, 2) _ (23, 3) _ (24, 4) _ (25, 5) \
|
|
_ (26, 6) _ (27, 7) _ (28, 8) _ (29, 9) _ (30, 10) _ (31, 11)
|
|
|
|
#ifdef __ALTIVEC__
|
|
#define CLIB_POWERPC_ALTIVEC_N_REGS 12
|
|
#else
|
|
#define CLIB_POWERPC_ALTIVEC_N_REGS 0
|
|
#endif
|
|
|
|
.global cdecl(clib_setjmp)
|
|
.align 4
|
|
.type cdecl(clib_setjmp), @function
|
|
cdecl(clib_setjmp):
|
|
mflr 0
|
|
stw 0, 4*0(3)
|
|
stw 1, 4*1(3)
|
|
mfcr 0
|
|
stw 0, 4*2(3)
|
|
#if CLIB_POWERPC_ALTIVEC_N_REGS > 0
|
|
mfspr 0, 256
|
|
#endif
|
|
stw 0, 4*3(3)
|
|
|
|
#if CLIB_POWERPC_ALTIVEC_N_REGS > 0
|
|
li 5, 4*4
|
|
#define _(a,b) stvx a, 3, 5 ; addi 5, 5, 16 ;
|
|
_foreach_20_31
|
|
#undef _
|
|
#endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */
|
|
|
|
/* gp 14 - 31 */
|
|
#define _(a,b) stw a, 4*(1*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 0*18)(3) ;
|
|
_foreach_14_31
|
|
#undef _
|
|
|
|
/* fp 14 - 31 */
|
|
#define _(a,b) stfd a, 4*(2*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 1*18)(3) ;
|
|
_foreach_14_31
|
|
#undef _
|
|
|
|
/* Return value. */
|
|
mr 3, 4
|
|
|
|
blr
|
|
|
|
.global cdecl(clib_longjmp)
|
|
.align 4
|
|
.type cdecl(clib_longjmp), @function
|
|
cdecl(clib_longjmp):
|
|
|
|
lwz 0, 4*0(3)
|
|
mtlr 0
|
|
lwz 1, 4*1(3)
|
|
lwz 0, 4*2(3)
|
|
mtcr 0
|
|
lwz 0, 4*3(3)
|
|
#if CLIB_POWERPC_ALTIVEC_N_REGS > 0
|
|
mtspr 256, 0
|
|
#endif
|
|
|
|
#if CLIB_POWERPC_ALTIVEC_N_REGS > 0
|
|
li 5, 4*4
|
|
#define _(a,b) lvx a, 3, 5 ; addi 5, 5, 16 ;
|
|
_foreach_20_31
|
|
#undef _
|
|
#endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */
|
|
|
|
/* gp 14 - 31 */
|
|
#define _(a,b) lwz a, 4*(1*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 0*18)(3) ;
|
|
_foreach_14_31
|
|
#undef _
|
|
|
|
/* fp 14 - 31 */
|
|
#define _(a,b) lfd a, 4*(2*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 1*18)(3) ;
|
|
_foreach_14_31
|
|
#undef _
|
|
|
|
/* Return value. */
|
|
mr 3, 4
|
|
|
|
blr
|
|
|
|
.global cdecl(clib_calljmp)
|
|
.align 4
|
|
.type cdecl(clib_calljmp), @function
|
|
cdecl(clib_calljmp):
|
|
/* Make sure stack is 16 byte aligned. */
|
|
andi. 0, 5, 0xf
|
|
sub 5, 5, 0
|
|
addi 5, 5, -16
|
|
|
|
/* Save old stack/link pointer on new stack. */
|
|
stw 1, 0(5)
|
|
mflr 0
|
|
stw 0, 4(5)
|
|
|
|
/* account for (sp, lr) tuple, and keep aligned */
|
|
addi 5, 5, -16
|
|
|
|
/* Switch stacks. */
|
|
mr 1, 5
|
|
|
|
/* Move argument into place. */
|
|
mtctr 3
|
|
mr 3, 4
|
|
|
|
/* Away we go. */
|
|
bctrl
|
|
|
|
/* back to our synthetic frame */
|
|
addi 1,1,16
|
|
|
|
/* Switch back to old stack. */
|
|
lwz 0, 4(1)
|
|
mtlr 0
|
|
lwz 0, 0(1)
|
|
mr 1, 0
|
|
|
|
/* Return to caller. */
|
|
blr
|
|
|
|
#elif defined(__arm__)
|
|
|
|
.global cdecl(clib_setjmp)
|
|
.align 4
|
|
.type cdecl(clib_setjmp), %function
|
|
cdecl(clib_setjmp):
|
|
mov ip, r0 /* jmp buffer */
|
|
|
|
/* Save integer registers */
|
|
stmia ip!, {v1-v6, sl, fp, sp, lr}
|
|
|
|
#ifdef __IWMMXT__
|
|
/* Save the call-preserved iWMMXt registers. */
|
|
wstrd wr10, [ip], #8
|
|
wstrd wr11, [ip], #8
|
|
wstrd wr12, [ip], #8
|
|
wstrd wr13, [ip], #8
|
|
wstrd wr14, [ip], #8
|
|
wstrd wr15, [ip], #8
|
|
#endif
|
|
|
|
/* Give back user's return value. */
|
|
mov r0, r1
|
|
bx lr
|
|
|
|
.global cdecl(clib_longjmp)
|
|
.align 4
|
|
.type cdecl(clib_longjmp), %function
|
|
cdecl(clib_longjmp):
|
|
mov ip, r0 /* jmp buffer */
|
|
|
|
/* Restore integer registers. */
|
|
ldmia ip!, {v1-v6, sl, fp, sp, lr}
|
|
|
|
#ifdef __IWMMXT__
|
|
/* Save the call-preserved iWMMXt registers. */
|
|
wldrd wr10, [ip], #8
|
|
wldrd wr11, [ip], #8
|
|
wldrd wr12, [ip], #8
|
|
wldrd wr13, [ip], #8
|
|
wldrd wr14, [ip], #8
|
|
wldrd wr15, [ip], #8
|
|
#endif
|
|
|
|
/* Give back user's return value. */
|
|
mov r0, r1
|
|
bx lr
|
|
|
|
.global cdecl(clib_calljmp)
|
|
.align 4
|
|
.type cdecl(clib_calljmp), %function
|
|
cdecl(clib_calljmp):
|
|
/* Make sure stack is 8 byte aligned. */
|
|
bic r2, r2, #7
|
|
|
|
/* Allocate space for stack/link pointer on new stack. */
|
|
sub r2, r2, #8
|
|
|
|
/* Save old stack/link pointer on new stack. */
|
|
str sp, [r2, #0]
|
|
str lr, [r2, #4]
|
|
|
|
/* Switch stacks. */
|
|
mov sp, r2
|
|
|
|
/* Save function to call. */
|
|
mov ip, r0
|
|
|
|
/* Move argument into place. */
|
|
mov r0, r1
|
|
|
|
/* Away we go. */
|
|
bx ip
|
|
|
|
/* Switch back to old stack. */
|
|
ldr lr, [sp, #4]
|
|
ldr ip, [sp, #0]
|
|
mov sp, ip
|
|
|
|
/* Return to caller. */
|
|
bx lr
|
|
|
|
#elif defined(__xtensa__)
|
|
|
|
/* FIXME implement if needed. */
|
|
.global cdecl(clib_setjmp)
|
|
.align 4
|
|
.type cdecl(clib_setjmp), %function
|
|
cdecl(clib_setjmp):
|
|
1: j 1b
|
|
|
|
.global cdecl(clib_longjmp)
|
|
.align 4
|
|
.type cdecl(clib_longjmp), @function
|
|
cdecl(clib_longjmp):
|
|
1: j 1b
|
|
|
|
.global cdecl(clib_calljmp)
|
|
.align 4
|
|
.type cdecl(clib_calljmp), %function
|
|
cdecl(clib_calljmp):
|
|
1: j 1b
|
|
|
|
#elif defined(__TMS320C6X__)
|
|
|
|
/* FIXME implement if needed. */
|
|
.global cdecl(clib_setjmp)
|
|
.align 4
|
|
.type cdecl(clib_setjmp), %function
|
|
cdecl(clib_setjmp):
|
|
1: B .S1 1b
|
|
|
|
.global cdecl(clib_longjmp)
|
|
.align 4
|
|
.type cdecl(clib_longjmp), @function
|
|
cdecl(clib_longjmp):
|
|
1: B .S1 1b
|
|
|
|
.global cdecl(clib_calljmp)
|
|
.align 4
|
|
.type cdecl(clib_calljmp), %function
|
|
cdecl(clib_calljmp):
|
|
1: B .S1 1b
|
|
|
|
#elif defined(_mips) && __mips == 64
|
|
|
|
.global cdecl(clib_setjmp)
|
|
.align 8
|
|
.type cdecl(clib_setjmp), %function
|
|
cdecl(clib_setjmp):
|
|
sd $ra, 0($a0)
|
|
sd $sp, 8($a0)
|
|
sd $gp, 16($a0)
|
|
sd $16, 24($a0)
|
|
sd $17, 32($a0)
|
|
sd $18, 40($a0)
|
|
sd $19, 48($a0)
|
|
sd $20, 56($a0)
|
|
sd $21, 64($a0)
|
|
sd $22, 72($a0)
|
|
sd $23, 80($a0)
|
|
sd $30, 88($a0)
|
|
move $v0, $a1
|
|
jr $ra
|
|
nop
|
|
|
|
.global cdecl(clib_longjmp)
|
|
.align 8
|
|
.type cdecl(clib_longjmp), @function
|
|
cdecl(clib_longjmp):
|
|
move $v0, $a1
|
|
bne $v0, $0, 1f
|
|
nop
|
|
daddu $v0, $v0, 1
|
|
1:
|
|
ld $ra, 0($a0)
|
|
ld $sp, 8($a0)
|
|
ld $gp, 16($a0)
|
|
ld $16, 24($a0)
|
|
ld $17, 32($a0)
|
|
ld $18, 40($a0)
|
|
ld $19, 48($a0)
|
|
ld $20, 56($a0)
|
|
ld $21, 64($a0)
|
|
ld $22, 72($a0)
|
|
ld $23, 80($a0)
|
|
ld $30, 88($a0)
|
|
jr $ra
|
|
nop
|
|
|
|
.global cdecl(clib_calljmp)
|
|
.align 8
|
|
.type cdecl(clib_calljmp), %function
|
|
cdecl(clib_calljmp):
|
|
/* Force 16 byte alignment of the new stack */
|
|
li $t1, -16
|
|
and $t0, $a2, $t1
|
|
/* Save old ra/gp/sp on new stack */
|
|
daddiu $t0, $t0, (-24)
|
|
sd $ra, 0($t0)
|
|
sd $gp, 8($t0)
|
|
sd $sp, 16($t0)
|
|
/* Switch stacks */
|
|
move $sp, $t0
|
|
/* Away we go */
|
|
move $t9, $a0
|
|
move $a0, $a1
|
|
jalr $t9
|
|
nop
|
|
/* Switch back to old ra/gp/sp */
|
|
move $t0, $sp
|
|
ld $ra, 0($t0)
|
|
ld $gp, 8($t0)
|
|
ld $sp, 16($t0)
|
|
/* Return to caller */
|
|
jr $ra
|
|
nop
|
|
|
|
#elif defined (__aarch64__)
|
|
/*
|
|
Copyright (c) 2011, 2012 ARM Ltd
|
|
All rights reserved.
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions
|
|
are met:
|
|
1. Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
2. Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
3. The name of the company may not be used to endorse or promote
|
|
products derived from this software without specific prior written
|
|
permission.
|
|
THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
#define GPR_LAYOUT \
|
|
REG_PAIR (x19, x20, 0); \
|
|
REG_PAIR (x21, x22, 16); \
|
|
REG_PAIR (x23, x24, 32); \
|
|
REG_PAIR (x25, x26, 48); \
|
|
REG_PAIR (x27, x28, 64); \
|
|
REG_PAIR (x29, x30, 80); \
|
|
REG_ONE (x16, 96)
|
|
#define FPR_LAYOUT \
|
|
REG_PAIR ( d8, d9, 112); \
|
|
REG_PAIR (d10, d11, 128); \
|
|
REG_PAIR (d12, d13, 144); \
|
|
REG_PAIR (d14, d15, 160);
|
|
// int cdecl(clib_setjmp) (jmp_buf)
|
|
.global cdecl(clib_setjmp)
|
|
.type cdecl(clib_setjmp), %function
|
|
cdecl(clib_setjmp):
|
|
mov x16, sp
|
|
#define REG_PAIR(REG1, REG2, OFFS) stp REG1, REG2, [x0, OFFS]
|
|
#define REG_ONE(REG1, OFFS) str REG1, [x0, OFFS]
|
|
GPR_LAYOUT
|
|
FPR_LAYOUT
|
|
#undef REG_PAIR
|
|
#undef REG_ONE
|
|
mov x0, x1
|
|
ret
|
|
.size cdecl(clib_setjmp), .-cdecl(clib_setjmp)
|
|
// void cdecl(clib_longjmp) (jmp_buf, int) __attribute__ ((noreturn))
|
|
.global cdecl(clib_longjmp)
|
|
.type cdecl(clib_longjmp), %function
|
|
cdecl(clib_longjmp):
|
|
#define REG_PAIR(REG1, REG2, OFFS) ldp REG1, REG2, [x0, OFFS]
|
|
#define REG_ONE(REG1, OFFS) ldr REG1, [x0, OFFS]
|
|
GPR_LAYOUT
|
|
FPR_LAYOUT
|
|
#undef REG_PAIR
|
|
#undef REG_ONE
|
|
mov sp, x16
|
|
mov x0, x1
|
|
// cmp w1, #0
|
|
// cinc w0, w1, eq
|
|
// use br not ret, as ret is guaranteed to mispredict
|
|
br x30
|
|
.size cdecl(clib_longjmp), .-cdecl(clib_longjmp)
|
|
|
|
|
|
// void cdecl(clib_calljmp) (x0=function, x1=arg, x2=new_stack)
|
|
.global cdecl(clib_calljmp)
|
|
.type cdecl(clib_calljmp), %function
|
|
cdecl(clib_calljmp):
|
|
// save fn ptr
|
|
mov x3, x0
|
|
// set up fn arg
|
|
mov x0, x1
|
|
// switch stacks
|
|
mov x4, sp
|
|
|
|
// space for saved sp, lr on new stack
|
|
sub x2, x2, #16
|
|
mov sp, x2
|
|
|
|
// save old sp and link register on new stack
|
|
str x4, [sp]
|
|
str x30,[sp,#8]
|
|
mov x4, sp
|
|
|
|
// go there
|
|
blr x3
|
|
|
|
// restore old sp and link register
|
|
mov x4, sp
|
|
|
|
ldr x3, [x4]
|
|
ldr x30,[x4, #8]
|
|
mov sp, x3
|
|
ret
|
|
.size cdecl(clib_calljmp), .-cdecl(clib_calljmp)
|
|
#else
|
|
#error "unknown machine"
|
|
#endif
|
|
|
|
#ifndef __APPLE__
|
|
.section .note.GNU-stack,"",%progbits
|
|
#endif
|