URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libffi/] [src/] [arm/] [sysv.S] - Rev 732
Compare with Previous | Blame | View Log
/* -----------------------------------------------------------------------sysv.S - Copyright (c) 1998, 2008 Red Hat, Inc.ARM Foreign Function InterfacePermission is hereby granted, free of charge, to any person obtaininga copy of this software and associated documentation files (the``Software''), to deal in the Software without restriction, includingwithout limitation the rights to use, copy, modify, merge, publish,distribute, sublicense, and/or sell copies of the Software, and topermit persons to whom the Software is furnished to do so, subject tothe following conditions:The above copyright notice and this permission notice shall be includedin 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 OFMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE ANDNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHTHOLDERS 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 OTHERDEALINGS IN THE SOFTWARE.----------------------------------------------------------------------- */#define LIBFFI_ASM#include <fficonfig.h>#include <ffi.h>#ifdef HAVE_MACHINE_ASM_H#include <machine/asm.h>#else#ifdef __USER_LABEL_PREFIX__#define CONCAT1(a, b) CONCAT2(a, b)#define CONCAT2(a, b) a ## b/* Use the right prefix for global labels. */#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)#else#define CNAME(x) x#endif#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):#endif#ifdef __ELF__#define LSYM(x) .x#else#define LSYM(x) x#endif/* We need a better way of testing for this, but for now, this is allwe can do. */@ This selects the minimum architecture level required.#define __ARM_ARCH__ 3#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)# undef __ARM_ARCH__# define __ARM_ARCH__ 4#endif#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \|| defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \|| defined(__ARM_ARCH_5TEJ__)# undef __ARM_ARCH__# define __ARM_ARCH__ 5#endif#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \|| defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \|| defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \|| defined(__ARM_ARCH_6M__)# undef __ARM_ARCH__# define __ARM_ARCH__ 6#endif#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \|| defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \|| defined(__ARM_ARCH_7EM__)# undef __ARM_ARCH__# define __ARM_ARCH__ 7#endif#if __ARM_ARCH__ >= 5# define call_reg(x) blx x#elif defined (__ARM_ARCH_4T__)# define call_reg(x) mov lr, pc ; bx x# if defined(__thumb__) || defined(__THUMB_INTERWORK__)# define __INTERWORKING__# endif#else# define call_reg(x) mov lr, pc ; mov pc, x#endif/* Conditionally compile unwinder directives. */#ifdef __ARM_EABI__#define UNWIND#else#define UNWIND @#endif#if defined(__thumb__) && !defined(__THUMB_INTERWORK__).macro ARM_FUNC_START name.text.align 0.thumb.thumb_funcENTRY(\name)bx pcnop.armUNWIND .fnstart/* A hook to tell gdb that we've switched to ARM mode. Also used to calldirectly from other local arm routines. */_L__\name:.endm#else.macro ARM_FUNC_START name.text.align 0.armENTRY(\name)UNWIND .fnstart.endm#endif.macro RETLDM regs=, cond=, dirn=ia#if defined (__INTERWORKING__).ifc "\regs",""ldr\cond lr, [sp], #4.elseldm\cond\dirn sp!, {\regs, lr}.endifbx\cond lr#else.ifc "\regs",""ldr\cond pc, [sp], #4.elseldm\cond\dirn sp!, {\regs, pc}.endif#endif.endm@ r0: fn@ r1: &ecif@ r2: cif->bytes@ r3: fig->flags@ sp+0: ecif.rvalue@ This assumes we are using gas.ARM_FUNC_START ffi_call_SYSV@ Save registersstmfd sp!, {r0-r3, fp, lr}UNWIND .save {r0-r3, fp, lr}mov fp, spUNWIND .setfp fp, sp@ Make room for all of the new args.sub sp, fp, r2@ Place all of the ffi_prep_args in positionmov r0, sp@ r1 already set@ Call ffi_prep_args(stack, &ecif)bl ffi_prep_args@ move first 4 parameters in registersldmia sp, {r0-r3}@ and adjust stacksub lr, fp, sp @ cif->bytes == fp - spldr ip, [fp] @ load fn() in advancecmp lr, #16movhs lr, #16add sp, sp, lr@ call (fn) (...)call_reg(ip)@ Remove the space we pushed for the argsmov sp, fp@ Load r2 with the pointer to storage for the return valueldr r2, [sp, #24]@ Load r3 with the return type codeldr r3, [sp, #12]@ If the return value pointer is NULL, assume no return value.cmp r2, #0beq LSYM(Lepilogue)@ return INTcmp r3, #FFI_TYPE_INT#if defined(__SOFTFP__) || defined(__ARM_EABI__)cmpne r3, #FFI_TYPE_FLOAT#endifstreq r0, [r2]beq LSYM(Lepilogue)@ return INT64cmp r3, #FFI_TYPE_SINT64#if defined(__SOFTFP__) || defined(__ARM_EABI__)cmpne r3, #FFI_TYPE_DOUBLE#endifstmeqia r2, {r0, r1}#if !defined(__SOFTFP__) && !defined(__ARM_EABI__)beq LSYM(Lepilogue)@ return FLOATcmp r3, #FFI_TYPE_FLOATstfeqs f0, [r2]beq LSYM(Lepilogue)@ return DOUBLE or LONGDOUBLEcmp r3, #FFI_TYPE_DOUBLEstfeqd f0, [r2]#endifLSYM(Lepilogue):RETLDM "r0-r3,fp".ffi_call_SYSV_end:UNWIND .fnend.size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)/*unsigned int FFI_HIDDENffi_closure_SYSV_inner (closure, respp, args)ffi_closure *closure;void **respp;void *args;*/ARM_FUNC_START ffi_closure_SYSVUNWIND .pad #16add ip, sp, #16stmfd sp!, {ip, lr}UNWIND .save {r0, lr}add r2, sp, #8UNWIND .pad #16sub sp, sp, #16str sp, [sp, #8]add r1, sp, #8bl ffi_closure_SYSV_innercmp r0, #FFI_TYPE_INTbeq .Lretintcmp r0, #FFI_TYPE_FLOAT#if defined(__SOFTFP__) || defined(__ARM_EABI__)beq .Lretint#elsebeq .Lretfloat#endifcmp r0, #FFI_TYPE_DOUBLE#if defined(__SOFTFP__) || defined(__ARM_EABI__)beq .Lretlonglong#elsebeq .Lretdouble#endifcmp r0, #FFI_TYPE_LONGDOUBLE#if defined(__SOFTFP__) || defined(__ARM_EABI__)beq .Lretlonglong#elsebeq .Lretlongdouble#endifcmp r0, #FFI_TYPE_SINT64beq .Lretlonglong.Lclosure_epilogue:add sp, sp, #16ldmfd sp, {sp, pc}.Lretint:ldr r0, [sp]b .Lclosure_epilogue.Lretlonglong:ldr r0, [sp]ldr r1, [sp, #4]b .Lclosure_epilogue#if !defined(__SOFTFP__) && !defined(__ARM_EABI__).Lretfloat:ldfs f0, [sp]b .Lclosure_epilogue.Lretdouble:ldfd f0, [sp]b .Lclosure_epilogue.Lretlongdouble:ldfd f0, [sp]b .Lclosure_epilogue#endif.ffi_closure_SYSV_end:UNWIND .fnend.size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)/* Below are VFP hard-float ABI call and closure implementations.Add VFP FPU directive here. */.fpu vfp@ r0: fn@ r1: &ecif@ r2: cif->bytes@ r3: fig->flags@ sp+0: ecif.rvalueARM_FUNC_START ffi_call_VFP@ Save registersstmfd sp!, {r0-r3, fp, lr}UNWIND .save {r0-r3, fp, lr}mov fp, spUNWIND .setfp fp, sp@ Make room for all of the new args.sub sp, sp, r2@ Make room for loading VFP argssub sp, sp, #64@ Place all of the ffi_prep_args in positionmov r0, sp@ r1 already setsub r2, fp, #64 @ VFP scratch space@ Call ffi_prep_args(stack, &ecif, vfp_space)bl ffi_prep_args@ Load VFP register args if neededcmp r0, #0beq LSYM(Lbase_args)@ Load only d0 if possiblecmp r0, #3sub ip, fp, #64flddle d0, [ip]fldmiadgt ip, {d0-d7}LSYM(Lbase_args):@ move first 4 parameters in registersldmia sp, {r0-r3}@ and adjust stacksub lr, ip, sp @ cif->bytes == (fp - 64) - spldr ip, [fp] @ load fn() in advancecmp lr, #16movhs lr, #16add sp, sp, lr@ call (fn) (...)call_reg(ip)@ Remove the space we pushed for the argsmov sp, fp@ Load r2 with the pointer to storage for@ the return valueldr r2, [sp, #24]@ Load r3 with the return type codeldr r3, [sp, #12]@ If the return value pointer is NULL,@ assume no return value.cmp r2, #0beq LSYM(Lepilogue_vfp)cmp r3, #FFI_TYPE_INTstreq r0, [r2]beq LSYM(Lepilogue_vfp)cmp r3, #FFI_TYPE_SINT64stmeqia r2, {r0, r1}beq LSYM(Lepilogue_vfp)cmp r3, #FFI_TYPE_FLOATfstseq s0, [r2]beq LSYM(Lepilogue_vfp)cmp r3, #FFI_TYPE_DOUBLEfstdeq d0, [r2]beq LSYM(Lepilogue_vfp)cmp r3, #FFI_TYPE_STRUCT_VFP_FLOATcmpne r3, #FFI_TYPE_STRUCT_VFP_DOUBLEfstmiadeq r2, {d0-d3}LSYM(Lepilogue_vfp):RETLDM "r0-r3,fp".ffi_call_VFP_end:UNWIND .fnend.size CNAME(ffi_call_VFP),.ffi_call_VFP_end-CNAME(ffi_call_VFP)ARM_FUNC_START ffi_closure_VFPfstmfdd sp!, {d0-d7}@ r0-r3, then d0-d7UNWIND .pad #80add ip, sp, #80stmfd sp!, {ip, lr}UNWIND .save {r0, lr}add r2, sp, #72add r3, sp, #8UNWIND .pad #72sub sp, sp, #72str sp, [sp, #64]add r1, sp, #64bl ffi_closure_SYSV_innercmp r0, #FFI_TYPE_INTbeq .Lretint_vfpcmp r0, #FFI_TYPE_FLOATbeq .Lretfloat_vfpcmp r0, #FFI_TYPE_DOUBLEcmpne r0, #FFI_TYPE_LONGDOUBLEbeq .Lretdouble_vfpcmp r0, #FFI_TYPE_SINT64beq .Lretlonglong_vfpcmp r0, #FFI_TYPE_STRUCT_VFP_FLOATbeq .Lretfloat_struct_vfpcmp r0, #FFI_TYPE_STRUCT_VFP_DOUBLEbeq .Lretdouble_struct_vfp.Lclosure_epilogue_vfp:add sp, sp, #72ldmfd sp, {sp, pc}.Lretfloat_vfp:flds s0, [sp]b .Lclosure_epilogue_vfp.Lretdouble_vfp:fldd d0, [sp]b .Lclosure_epilogue_vfp.Lretint_vfp:ldr r0, [sp]b .Lclosure_epilogue_vfp.Lretlonglong_vfp:ldmia sp, {r0, r1}b .Lclosure_epilogue_vfp.Lretfloat_struct_vfp:fldmiad sp, {d0-d1}b .Lclosure_epilogue_vfp.Lretdouble_struct_vfp:fldmiad sp, {d0-d3}b .Lclosure_epilogue_vfp.ffi_closure_VFP_end:UNWIND .fnend.size CNAME(ffi_closure_VFP),.ffi_closure_VFP_end-CNAME(ffi_closure_VFP)ENTRY(ffi_arm_trampoline)stmfd sp!, {r0-r3}ldr r0, [pc]ldr pc, [pc]#if defined __ELF__ && defined __linux__.section .note.GNU-stack,"",%progbits#endif
