URL
https://opencores.org/ocsvn/scarts/scarts/trunk
Subversion Repositories scarts
[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libffi/] [src/] [arm/] [sysv.S] - Rev 14
Compare with Previous | Blame | View Log
/* -----------------------------------------------------------------------sysv.S - Copyright (c) 1998 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, EXPRESSOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OFMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OROTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OROTHER DEALINGS 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__)# undef __ARM_ARCH__# define __ARM_ARCH__ 6#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#if defined(__thumb__) && !defined(__THUMB_INTERWORK__).macro ARM_FUNC_START name.text.align 0.thumb.thumb_funcENTRY(\name)bx pcnop.arm/* 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).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: ffi_prep_args@ r1: &ecif@ r2: cif->bytes@ r3: fig->flags@ sp+0: ecif.rvalue@ sp+4: fn@ This assumes we are using gas.ARM_FUNC_START ffi_call_SYSV@ Save registersstmfd sp!, {r0-r3, fp, lr}mov fp, sp@ Make room for all of the new args.sub sp, fp, r2@ Place all of the ffi_prep_args in positionmov ip, r0mov r0, sp@ r1 already set@ Call ffi_prep_args(stack, &ecif)call_reg(ip)@ move first 4 parameters in registersldmia sp, {r0-r3}@ and adjust stackldr ip, [fp, #8]cmp ip, #16movhs ip, #16add sp, sp, ip@ call (fn) (...)ldr ip, [fp, #28]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#ifdef __SOFTFP__cmpne r3, #FFI_TYPE_FLOAT#endifstreq r0, [r2]beq LSYM(Lepilogue)@ return INT64cmp r3, #FFI_TYPE_SINT64#ifdef __SOFTFP__cmpne r3, #FFI_TYPE_DOUBLE#endifstmeqia r2, {r0, r1}#ifndef __SOFTFP__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:.size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
