From cb642590f317e30bd870b47934dac12a71f320b1 Mon Sep 17 00:00:00 2001 From: Andrew Haley Date: Tue, 4 Sep 2007 17:52:45 +0000 Subject: [multiple changes] 2007-09-04 * src/arm/sysv.S (UNWIND): New. (Whole file): Conditionally compile unwinder directives. * src/arm/sysv.S: Add unwinder directives. * src/arm/ffi.c (ffi_prep_args): Align structs by at least 4 bytes. Only treat r0 as a struct address if we're actually returning a struct by address. Only copy the bytes that are actually within a struct. (ffi_prep_cif_machdep): A Composite Type not larger than 4 bytes is returned in r0, not passed by address. (ffi_call): Allocate a word-sized temporary for the case where a composite is returned in r0. (ffi_prep_incoming_args_SYSV): Align as necessary. 2007-08-05 Steven Newbury * src/arm/ffi.c (FFI_INIT_TRAMPOLINE): Use __clear_cache instead of directly using the sys_cacheflush syscall. 2007-07-27 Andrew Haley * src/arm/sysv.S (ffi_closure_SYSV): Add soft-float. From-SVN: r128093 --- libffi/ChangeLog | 25 ++++++++++++++++++++ libffi/src/arm/ffi.c | 63 +++++++++++++++++++++++++++++++++------------------ libffi/src/arm/sysv.S | 38 +++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 22 deletions(-) (limited to 'libffi') diff --git a/libffi/ChangeLog b/libffi/ChangeLog index 5ea8207..0f434c8 100644 --- a/libffi/ChangeLog +++ b/libffi/ChangeLog @@ -1,3 +1,28 @@ +2007-09-04 + + * src/arm/sysv.S (UNWIND): New. + (Whole file): Conditionally compile unwinder directives. + * src/arm/sysv.S: Add unwinder directives. + + * src/arm/ffi.c (ffi_prep_args): Align structs by at least 4 bytes. + Only treat r0 as a struct address if we're actually returning a + struct by address. + Only copy the bytes that are actually within a struct. + (ffi_prep_cif_machdep): A Composite Type not larger than 4 bytes + is returned in r0, not passed by address. + (ffi_call): Allocate a word-sized temporary for the case where + a composite is returned in r0. + (ffi_prep_incoming_args_SYSV): Align as necessary. + +2007-08-05 Steven Newbury + + * src/arm/ffi.c (FFI_INIT_TRAMPOLINE): Use __clear_cache instead of + directly using the sys_cacheflush syscall. + +2007-07-27 Andrew Haley + + * src/arm/sysv.S (ffi_closure_SYSV): Add soft-float. + 2007-09-03 Maciej W. Rozycki * Makefile.am: Unify MIPS_IRIX and MIPS_LINUX into MIPS. diff --git a/libffi/src/arm/ffi.c b/libffi/src/arm/ffi.c index f3cd506..35b2c34 100644 --- a/libffi/src/arm/ffi.c +++ b/libffi/src/arm/ffi.c @@ -40,7 +40,7 @@ void ffi_prep_args(char *stack, extended_cif *ecif) argp = stack; - if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) { + if ( ecif->cif->flags == FFI_TYPE_STRUCT ) { *(void **) argp = ecif->rvalue; argp += 4; } @@ -58,6 +58,9 @@ void ffi_prep_args(char *stack, extended_cif *ecif) argp = (char *) ALIGN(argp, (*p_arg)->alignment); } + if ((*p_arg)->type == FFI_TYPE_STRUCT) + argp = (char *) ALIGN(argp, 4); + z = (*p_arg)->size; if (z < sizeof(int)) { @@ -81,7 +84,7 @@ void ffi_prep_args(char *stack, extended_cif *ecif) break; case FFI_TYPE_STRUCT: - *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); + memcpy(argp, *p_argv, (*p_arg)->size); break; default: @@ -115,7 +118,6 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) switch (cif->rtype->type) { case FFI_TYPE_VOID: - case FFI_TYPE_STRUCT: case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: cif->flags = (unsigned) cif->rtype->type; @@ -126,6 +128,17 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) cif->flags = (unsigned) FFI_TYPE_SINT64; break; + case FFI_TYPE_STRUCT: + if (cif->rtype->size <= 4) + /* A Composite Type not larger than 4 bytes is returned in r0. */ + cif->flags = (unsigned)FFI_TYPE_INT; + else + /* A Composite Type larger than 4 bytes, or whose size cannot + be determined statically ... is stored in memory at an + address passed [in r0]. */ + cif->flags = (unsigned)FFI_TYPE_STRUCT; + break; + default: cif->flags = FFI_TYPE_INT; break; @@ -141,21 +154,27 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue) { extended_cif ecif; + int small_struct = (cif->flags == FFI_TYPE_INT + && cif->rtype->type == FFI_TYPE_STRUCT); + ecif.cif = cif; ecif.avalue = avalue; + + unsigned int temp; /* If the return value is a struct and we don't have a return */ /* value address then we need to make one */ if ((rvalue == NULL) && - (cif->rtype->type == FFI_TYPE_STRUCT)) + (cif->flags == FFI_TYPE_STRUCT)) { ecif.rvalue = alloca(cif->rtype->size); } + else if (small_struct) + ecif.rvalue = &temp; else ecif.rvalue = rvalue; - - + switch (cif->abi) { case FFI_SYSV: @@ -167,6 +186,8 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue) FFI_ASSERT(0); break; } + if (small_struct) + memcpy (rvalue, &temp, cif->rtype->size); } /** private members **/ @@ -228,9 +249,12 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, { size_t z; + size_t alignment = (*p_arg)->alignment; + if (alignment < 4) + alignment = 4; /* Align if necessary */ - if ((sizeof(int) - 1) & (unsigned) argp) { - argp = (char *) ALIGN(argp, sizeof(int)); + if ((alignment - 1) & (unsigned) argp) { + argp = (char *) ALIGN(argp, alignment); } z = (*p_arg)->size; @@ -248,21 +272,16 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, /* How to make a trampoline. */ -#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \ -({ unsigned char *__tramp = (unsigned char*)(TRAMP); \ - unsigned int __fun = (unsigned int)(FUN); \ - unsigned int __ctx = (unsigned int)(CTX); \ +#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \ +({ unsigned char *__tramp = (unsigned char*)(TRAMP); \ + unsigned int __fun = (unsigned int)(FUN); \ + unsigned int __ctx = (unsigned int)(CTX); \ *(unsigned int*) &__tramp[0] = 0xe92d000f; /* stmfd sp!, {r0-r3} */ \ - *(unsigned int*) &__tramp[4] = 0xe59f0000; /* ldr r0, [pc] */ \ - *(unsigned int*) &__tramp[8] = 0xe59ff000; /* ldr pc, [pc] */ \ - *(unsigned int*) &__tramp[12] = __ctx; \ - *(unsigned int*) &__tramp[16] = __fun; \ - register unsigned long _beg __asm ("a1") = (unsigned long) (&__tramp[0]); \ - register unsigned long _end __asm ("a2") = (unsigned long) (&__tramp[19]); \ - register unsigned long _flg __asm ("a3") = 0; \ - __asm __volatile ("swi 0x9f0002 @ sys_cacheflush" \ - : "=r" (_beg) \ - : "0" (_beg), "r" (_end), "r" (_flg)); \ + *(unsigned int*) &__tramp[4] = 0xe59f0000; /* ldr r0, [pc] */ \ + *(unsigned int*) &__tramp[8] = 0xe59ff000; /* ldr pc, [pc] */ \ + *(unsigned int*) &__tramp[12] = __ctx; \ + *(unsigned int*) &__tramp[16] = __fun; \ + __clear_cache((&__tramp[0]), (&__tramp[19])); \ }) diff --git a/libffi/src/arm/sysv.S b/libffi/src/arm/sysv.S index 00f43b2..12876d1 100644 --- a/libffi/src/arm/sysv.S +++ b/libffi/src/arm/sysv.S @@ -82,6 +82,14 @@ # 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 @@ -92,6 +100,7 @@ bx pc nop .arm + UNWIND .fnstart /* A hook to tell gdb that we've switched to ARM mode. Also used to call directly from other local arm routines. */ _L__\name: @@ -102,6 +111,7 @@ _L__\name: .align 0 .arm ENTRY(\name) + UNWIND .fnstart .endm #endif @@ -134,8 +144,11 @@ _L__\name: ARM_FUNC_START ffi_call_SYSV @ Save registers stmfd sp!, {r0-r3, fp, lr} + UNWIND .save {r0-r3, fp, lr} mov fp, sp + UNWIND .setfp fp, sp + @ Make room for all of the new args. sub sp, fp, r2 @@ -205,6 +218,7 @@ LSYM(Lepilogue): RETLDM "r0-r3,fp" .ffi_call_SYSV_end: + UNWIND .fnend .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV) /* @@ -216,21 +230,40 @@ LSYM(Lepilogue): */ ARM_FUNC_START ffi_closure_SYSV + UNWIND .pad #16 add ip, sp, #16 stmfd sp!, {ip, lr} + UNWIND .save {r0, lr} add r2, sp, #8 + .pad #16 sub sp, sp, #16 str sp, [sp, #8] add r1, sp, #8 bl ffi_closure_SYSV_inner cmp r0, #FFI_TYPE_INT beq .Lretint + cmp r0, #FFI_TYPE_FLOAT +#ifdef __SOFTFP__ + beq .Lretint +#else beq .Lretfloat +#endif + cmp r0, #FFI_TYPE_DOUBLE +#ifdef __SOFTFP__ + beq .Lretlonglong +#else beq .Lretdouble +#endif + cmp r0, #FFI_TYPE_LONGDOUBLE +#ifdef __SOFTFP__ + beq .Lretlonglong +#else beq .Lretlongdouble +#endif + cmp r0, #FFI_TYPE_SINT64 beq .Lretlonglong .Lclosure_epilogue: @@ -243,6 +276,8 @@ ARM_FUNC_START ffi_closure_SYSV ldr r0, [sp] ldr r1, [sp, #4] b .Lclosure_epilogue + +#ifndef __SOFTFP__ .Lretfloat: ldfs f0, [sp] b .Lclosure_epilogue @@ -252,6 +287,9 @@ ARM_FUNC_START ffi_closure_SYSV .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) -- cgit v1.1