| Index: libffi/src/avr32/ffi.c |
| =================================================================== |
| --- /dev/null |
| +++ libffi/src/avr32/ffi.c |
| @@ -0,0 +1,421 @@ |
| +/* ----------------------------------------------------------------------- |
| + ffi.c - Copyright (c) 2009 Bradley Smith <brad@brad-smith.co.uk> |
| + |
| + AVR32 Foreign Function Interface |
| + |
| + 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. |
| + ----------------------------------------------------------------------- */ |
| + |
| +#include <ffi.h> |
| +#include <ffi_common.h> |
| + |
| +#include <stdlib.h> |
| +#include <stdio.h> |
| +#include <unistd.h> |
| +#include <asm/unistd.h> |
| + |
| +/* #define DEBUG */ |
| + |
| +extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, |
| + unsigned int, unsigned int, unsigned int*, unsigned int, |
| + void (*fn)(void)); |
| +extern void ffi_closure_SYSV (ffi_closure *); |
| + |
| +unsigned int pass_struct_on_stack(ffi_type *type) |
| +{ |
| + if(type->type != FFI_TYPE_STRUCT) |
| + return 0; |
| + |
| + if(type->alignment < type->size && |
| + !(type->size == 4 || type->size == 8) && |
| + !(type->size == 8 && type->alignment >= 4)) |
| + return 1; |
| + |
| + if(type->size == 3 || type->size == 5 || type->size == 6 || |
| + type->size == 7) |
| + return 1; |
| + |
| + return 0; |
| +} |
| + |
| +/* ffi_prep_args is called by the assembly routine once stack space |
| + * has been allocated for the function's arguments |
| + * |
| + * This is annoyingly complex since we need to keep track of used |
| + * registers. |
| + */ |
| + |
| +void ffi_prep_args(char *stack, extended_cif *ecif) |
| +{ |
| + unsigned int i; |
| + void **p_argv; |
| + ffi_type **p_arg; |
| + char *reg_base = stack; |
| + char *stack_base = stack + 20; |
| + unsigned int stack_offset = 0; |
| + unsigned int reg_mask = 0; |
| + |
| + p_argv = ecif->avalue; |
| + |
| + /* If cif->flags is struct then we know it's not passed in registers */ |
| + if(ecif->cif->flags == FFI_TYPE_STRUCT) |
| + { |
| + *(void**)reg_base = ecif->rvalue; |
| + reg_mask |= 1; |
| + } |
| + |
| + for(i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs; |
| + i++, p_arg++) |
| + { |
| + size_t z = (*p_arg)->size; |
| + int alignment = (*p_arg)->alignment; |
| + int type = (*p_arg)->type; |
| + char *addr = 0; |
| + |
| + if(z % 4 != 0) |
| + z += (4 - z % 4); |
| + |
| + if(reg_mask != 0x1f) |
| + { |
| + if(pass_struct_on_stack(*p_arg)) |
| + { |
| + addr = stack_base + stack_offset; |
| + stack_offset += z; |
| + } |
| + else if(z == sizeof(int)) |
| + { |
| + char index = 0; |
| + |
| + while((reg_mask >> index) & 1) |
| + index++; |
| + |
| + addr = reg_base + (index * 4); |
| + reg_mask |= (1 << index); |
| + } |
| + else if(z == 2 * sizeof(int)) |
| + { |
| + if(!((reg_mask >> 1) & 1)) |
| + { |
| + addr = reg_base + 4; |
| + reg_mask |= (3 << 1); |
| + } |
| + else if(!((reg_mask >> 3) & 1)) |
| + { |
| + addr = reg_base + 12; |
| + reg_mask |= (3 << 3); |
| + } |
| + } |
| + } |
| + |
| + if(!addr) |
| + { |
| + addr = stack_base + stack_offset; |
| + stack_offset += z; |
| + } |
| + |
| + if(type == FFI_TYPE_STRUCT && (*p_arg)->elements[1] == NULL) |
| + type = (*p_arg)->elements[0]->type; |
| + |
| + switch(type) |
| + { |
| + case FFI_TYPE_UINT8: |
| + *(unsigned int *)addr = (unsigned int)*(UINT8 *)(*p_argv); |
| + break; |
| + case FFI_TYPE_SINT8: |
| + *(signed int *)addr = (signed int)*(SINT8 *)(*p_argv); |
| + break; |
| + case FFI_TYPE_UINT16: |
| + *(unsigned int *)addr = (unsigned int)*(UINT16 *)(*p_argv); |
| + break; |
| + case FFI_TYPE_SINT16: |
| + *(signed int *)addr = (signed int)*(SINT16 *)(*p_argv); |
| + break; |
| + default: |
| + memcpy(addr, *p_argv, z); |
| + } |
| + |
| + p_argv++; |
| + } |
| + |
| +#ifdef DEBUG |
| + /* Debugging */ |
| + for(i = 0; i < 5; i++) |
| + { |
| + if((reg_mask & (1 << i)) == 0) |
| + printf("r%d: (unused)\n", 12 - i); |
| + else |
| + printf("r%d: 0x%08x\n", 12 - i, ((unsigned int*)reg_base)[i]); |
| + } |
| + |
| + for(i = 0; i < stack_offset / 4; i++) |
| + { |
| + printf("sp+%d: 0x%08x\n", i*4, ((unsigned int*)stack_base)[i]); |
| + } |
| +#endif |
| +} |
| + |
| +/* Perform machine dependent cif processing */ |
| +ffi_status ffi_prep_cif_machdep(ffi_cif *cif) |
| +{ |
| + /* Round the stack up to a multiple of 8 bytes. This isn't needed |
| + * everywhere, but it is on some platforms, and it doesn't harm |
| + * anything when it isn't needed. */ |
| + cif->bytes = (cif->bytes + 7) & ~7; |
| + |
| + /* Flag to indicate that he return value is in fact a struct */ |
| + cif->rstruct_flag = 0; |
| + |
| + /* Set the return type flag */ |
| + switch(cif->rtype->type) |
| + { |
| + case FFI_TYPE_SINT8: |
| + case FFI_TYPE_UINT8: |
| + cif->flags = (unsigned)FFI_TYPE_UINT8; |
| + break; |
| + case FFI_TYPE_SINT16: |
| + case FFI_TYPE_UINT16: |
| + cif->flags = (unsigned)FFI_TYPE_UINT16; |
| + break; |
| + case FFI_TYPE_FLOAT: |
| + case FFI_TYPE_SINT32: |
| + case FFI_TYPE_UINT32: |
| + case FFI_TYPE_POINTER: |
| + cif->flags = (unsigned)FFI_TYPE_UINT32; |
| + break; |
| + case FFI_TYPE_DOUBLE: |
| + case FFI_TYPE_SINT64: |
| + case FFI_TYPE_UINT64: |
| + cif->flags = (unsigned)FFI_TYPE_UINT64; |
| + break; |
| + case FFI_TYPE_STRUCT: |
| + cif->rstruct_flag = 1; |
| + if(!pass_struct_on_stack(cif->rtype)) |
| + { |
| + if(cif->rtype->size <= 1) |
| + cif->flags = (unsigned)FFI_TYPE_UINT8; |
| + else if(cif->rtype->size <= 2) |
| + cif->flags = (unsigned)FFI_TYPE_UINT16; |
| + else if(cif->rtype->size <= 4) |
| + cif->flags = (unsigned)FFI_TYPE_UINT32; |
| + else if(cif->rtype->size <= 8) |
| + cif->flags = (unsigned)FFI_TYPE_UINT64; |
| + else |
| + cif->flags = (unsigned)cif->rtype->type; |
| + } |
| + else |
| + cif->flags = (unsigned)cif->rtype->type; |
| + break; |
| + default: |
| + cif->flags = (unsigned)cif->rtype->type; |
| + break; |
| + } |
| + |
| + return FFI_OK; |
| +} |
| + |
| +void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) |
| +{ |
| + extended_cif ecif; |
| + |
| + unsigned int size = 0, i = 0; |
| + ffi_type **p_arg; |
| + |
| + ecif.cif = cif; |
| + ecif.avalue = avalue; |
| + |
| + for(i = 0, p_arg = cif->arg_types; i < cif->nargs; i++, p_arg++) |
| + size += (*p_arg)->size + (4 - (*p_arg)->size % 4); |
| + |
| + /* If the return value is a struct and we don't have a return value |
| + * address then we need to make one */ |
| + |
| + /* If cif->flags is struct then it's not suitable for registers */ |
| + if((rvalue == NULL) && (cif->flags == FFI_TYPE_STRUCT)) |
| + ecif.rvalue = alloca(cif->rtype->size); |
| + else |
| + ecif.rvalue = rvalue; |
| + |
| + switch(cif->abi) |
| + { |
| + case FFI_SYSV: |
| + ffi_call_SYSV(ffi_prep_args, &ecif, size, cif->flags, |
| + ecif.rvalue, cif->rstruct_flag, fn); |
| + break; |
| + default: |
| + FFI_ASSERT(0); |
| + break; |
| + } |
| +} |
| + |
| +static void ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, |
| + void **avalue, ffi_cif *cif) |
| +{ |
| + register unsigned int i, reg_mask = 0; |
| + register void **p_argv; |
| + register ffi_type **p_arg; |
| + register char *reg_base = stack; |
| + register char *stack_base = stack + 20; |
| + register unsigned int stack_offset = 0; |
| + |
| +#ifdef DEBUG |
| + /* Debugging */ |
| + for(i = 0; i < cif->nargs + 7; i++) |
| + { |
| + printf("sp+%d: 0x%08x\n", i*4, ((unsigned int*)stack)[i]); |
| + } |
| +#endif |
| + |
| + /* If cif->flags is struct then we know it's not passed in registers */ |
| + if(cif->flags == FFI_TYPE_STRUCT) |
| + { |
| + *rvalue = *(void **)reg_base; |
| + reg_mask |= 1; |
| + } |
| + |
| + p_argv = avalue; |
| + |
| + for(i = 0, p_arg = cif->arg_types; i < cif->nargs; i++, p_arg++) |
| + { |
| + size_t z = (*p_arg)->size; |
| + int alignment = (*p_arg)->alignment; |
| + |
| + *p_argv = 0; |
| + |
| + if(z % 4 != 0) |
| + z += (4 - z % 4); |
| + |
| + if(reg_mask != 0x1f) |
| + { |
| + if(pass_struct_on_stack(*p_arg)) |
| + { |
| + *p_argv = (void*)stack_base + stack_offset; |
| + stack_offset += z; |
| + } |
| + else if(z <= sizeof(int)) |
| + { |
| + char index = 0; |
| + |
| + while((reg_mask >> index) & 1) |
| + index++; |
| + |
| + *p_argv = (void*)reg_base + (index * 4); |
| + reg_mask |= (1 << index); |
| + } |
| + else if(z == 2 * sizeof(int)) |
| + { |
| + if(!((reg_mask >> 1) & 1)) |
| + { |
| + *p_argv = (void*)reg_base + 4; |
| + reg_mask |= (3 << 1); |
| + } |
| + else if(!((reg_mask >> 3) & 1)) |
| + { |
| + *p_argv = (void*)reg_base + 12; |
| + reg_mask |= (3 << 3); |
| + } |
| + } |
| + } |
| + |
| + if(!*p_argv) |
| + { |
| + *p_argv = (void*)stack_base + stack_offset; |
| + stack_offset += z; |
| + } |
| + |
| + if((*p_arg)->type != FFI_TYPE_STRUCT || |
| + (*p_arg)->elements[1] == NULL) |
| + { |
| + if(alignment == 1) |
| + **(unsigned int**)p_argv <<= 24; |
| + else if(alignment == 2) |
| + **(unsigned int**)p_argv <<= 16; |
| + } |
| + |
| + p_argv++; |
| + } |
| + |
| +#ifdef DEBUG |
| + /* Debugging */ |
| + for(i = 0; i < cif->nargs; i++) |
| + { |
| + printf("sp+%d: 0x%08x\n", i*4, *(((unsigned int**)avalue)[i])); |
| + } |
| +#endif |
| +} |
| + |
| +/* This function is jumped to by the trampoline */ |
| + |
| +unsigned int ffi_closure_SYSV_inner(ffi_closure *closure, void **respp, |
| + void *args) |
| +{ |
| + ffi_cif *cif; |
| + void **arg_area; |
| + unsigned int i, size = 0; |
| + ffi_type **p_arg; |
| + |
| + cif = closure->cif; |
| + |
| + for(i = 0, p_arg = cif->arg_types; i < cif->nargs; i++, p_arg++) |
| + size += (*p_arg)->size + (4 - (*p_arg)->size % 4); |
| + |
| + arg_area = (void **)alloca(size); |
| + |
| + /* this call will initialize ARG_AREA, such that each element in that |
| + * array points to the corresponding value on the stack; and if the |
| + * function returns a structure, it will re-set RESP to point to the |
| + * structure return address. */ |
| + |
| + ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif); |
| + |
| + (closure->fun)(cif, *respp, arg_area, closure->user_data); |
| + |
| + return cif->flags; |
| +} |
| + |
| +ffi_status ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif, |
| + void (*fun)(ffi_cif*, void*, void**, void*), void *user_data, |
| + void *codeloc) |
| +{ |
| + FFI_ASSERT(cif->abi == FFI_SYSV); |
| + |
| + unsigned char *__tramp = (unsigned char*)(&closure->tramp[0]); |
| + unsigned int __fun = (unsigned int)(&ffi_closure_SYSV); |
| + unsigned int __ctx = (unsigned int)(codeloc); |
| + unsigned int __rstruct_flag = (unsigned int)(cif->rstruct_flag); |
| + unsigned int __inner = (unsigned int)(&ffi_closure_SYSV_inner); |
| + *(unsigned int*) &__tramp[0] = 0xebcd1f00; /* pushm r8-r12 */ |
| + *(unsigned int*) &__tramp[4] = 0xfefc0010; /* ld.w r12, pc[16] */ |
| + *(unsigned int*) &__tramp[8] = 0xfefb0010; /* ld.w r11, pc[16] */ |
| + *(unsigned int*) &__tramp[12] = 0xfefa0010; /* ld.w r10, pc[16] */ |
| + *(unsigned int*) &__tramp[16] = 0xfeff0010; /* ld.w pc, pc[16] */ |
| + *(unsigned int*) &__tramp[20] = __ctx; |
| + *(unsigned int*) &__tramp[24] = __rstruct_flag; |
| + *(unsigned int*) &__tramp[28] = __inner; |
| + *(unsigned int*) &__tramp[32] = __fun; |
| + syscall(__NR_cacheflush, 0, (&__tramp[0]), 36); |
| + |
| + closure->cif = cif; |
| + closure->user_data = user_data; |
| + closure->fun = fun; |
| + |
| + return FFI_OK; |
| +} |
| + |
| Index: libffi/src/avr32/ffitarget.h |
| =================================================================== |
| --- /dev/null |
| +++ libffi/src/avr32/ffitarget.h |
| @@ -0,0 +1,50 @@ |
| +/* -----------------------------------------------------------------*-C-*- |
| + ffitarget.h - Copyright (c) 2009 Bradley Smith <brad@brad-smith.co.uk> |
| + Target configuration macros for AVR32. |
| + |
| + 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. |
| + |
| + ----------------------------------------------------------------------- */ |
| + |
| +#ifndef LIBFFI_TARGET_H |
| +#define LIBFFI_TARGET_H |
| + |
| +#ifndef LIBFFI_ASM |
| +typedef unsigned long ffi_arg; |
| +typedef signed long ffi_sarg; |
| + |
| +typedef enum ffi_abi { |
| + FFI_FIRST_ABI = 0, |
| + FFI_SYSV, |
| + FFI_DEFAULT_ABI = FFI_SYSV, |
| + FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 |
| +} ffi_abi; |
| +#endif |
| + |
| +#define FFI_EXTRA_CIF_FIELDS unsigned int rstruct_flag |
| + |
| +/* Definitions for closures */ |
| + |
| +#define FFI_CLOSURES 1 |
| +#define FFI_TRAMPOLINE_SIZE 36 |
| +#define FFI_NATIVE_RAW_API 0 |
| + |
| +#endif |
| Index: libffi/src/avr32/sysv.S |
| =================================================================== |
| --- /dev/null |
| +++ libffi/src/avr32/sysv.S |
| @@ -0,0 +1,208 @@ |
| +/* ----------------------------------------------------------------------- |
| + sysv.S - Copyright (c) 2009 Bradley Smith <brad@brad-smith.co.uk> |
| + |
| + AVR32 Foreign Function Interface |
| + |
| + 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. |
| + --------------------------------------------------------------------- */ |
| + |
| +#define LIBFFI_ASM |
| +#include <fficonfig.h> |
| +#include <ffi.h> |
| + |
| + /* r12: ffi_prep_args |
| + * r11: &ecif |
| + * r10: size |
| + * r9: cif->flags |
| + * r8: ecif.rvalue |
| + * sp+0: cif->rstruct_flag |
| + * sp+4: fn */ |
| + |
| + .text |
| + .align 1 |
| + .globl ffi_call_SYSV |
| + .type ffi_call_SYSV, @function |
| +ffi_call_SYSV: |
| + stm --sp, r0,r1,lr |
| + stm --sp, r8-r12 |
| + mov r0, sp |
| + |
| + /* Make room for all of the new args. */ |
| + sub sp, r10 |
| + /* Pad to make way for potential skipped registers */ |
| + sub sp, 20 |
| + |
| + /* Call ffi_prep_args(stack, &ecif). */ |
| + /* r11 already set */ |
| + mov r1, r12 |
| + mov r12, sp |
| + icall r1 |
| + |
| + /* Save new argument size */ |
| + mov r1, r12 |
| + |
| + /* Move first 5 parameters in registers. */ |
| + ldm sp++, r8-r12 |
| + |
| + /* call (fn) (...). */ |
| + ld.w r1, r0[36] |
| + icall r1 |
| + |
| + /* Remove the space we pushed for the args. */ |
| + mov sp, r0 |
| + |
| + /* Load r1 with the rstruct flag. */ |
| + ld.w r1, sp[32] |
| + |
| + /* Load r9 with the return type code. */ |
| + ld.w r9, sp[12] |
| + |
| + /* Load r8 with the return value pointer. */ |
| + ld.w r8, sp[16] |
| + |
| + /* If the return value pointer is NULL, assume no return value. */ |
| + cp.w r8, 0 |
| + breq .Lend |
| + |
| + /* Check if return type is actually a struct */ |
| + cp.w r1, 0 |
| + breq 1f |
| + |
| + /* Return 8bit */ |
| + cp.w r9, FFI_TYPE_UINT8 |
| + breq .Lstore8 |
| + |
| + /* Return 16bit */ |
| + cp.w r9, FFI_TYPE_UINT16 |
| + breq .Lstore16 |
| + |
| +1: |
| + /* Return 32bit */ |
| + cp.w r9, FFI_TYPE_UINT32 |
| + breq .Lstore32 |
| + cp.w r9, FFI_TYPE_UINT16 |
| + breq .Lstore32 |
| + cp.w r9, FFI_TYPE_UINT8 |
| + breq .Lstore32 |
| + |
| + /* Return 64bit */ |
| + cp.w r9, FFI_TYPE_UINT64 |
| + breq .Lstore64 |
| + |
| + /* Didn't match anything */ |
| + bral .Lend |
| + |
| +.Lstore64: |
| + st.w r8[0], r11 |
| + st.w r8[4], r10 |
| + bral .Lend |
| + |
| +.Lstore32: |
| + st.w r8[0], r12 |
| + bral .Lend |
| + |
| +.Lstore16: |
| + st.h r8[0], r12 |
| + bral .Lend |
| + |
| +.Lstore8: |
| + st.b r8[0], r12 |
| + bral .Lend |
| + |
| +.Lend: |
| + sub sp, -20 |
| + ldm sp++, r0,r1,pc |
| + |
| + .size ffi_call_SYSV, . - ffi_call_SYSV |
| + |
| + |
| + /* r12: __ctx |
| + * r11: __rstruct_flag |
| + * r10: __inner */ |
| + |
| + .align 1 |
| + .globl ffi_closure_SYSV |
| + .type ffi_closure_SYSV, @function |
| +ffi_closure_SYSV: |
| + stm --sp, r0,lr |
| + mov r0, r11 |
| + mov r8, r10 |
| + sub r10, sp, -8 |
| + sub sp, 12 |
| + st.w sp[8], sp |
| + sub r11, sp, -8 |
| + icall r8 |
| + |
| + /* Check if return type is actually a struct */ |
| + cp.w r0, 0 |
| + breq 1f |
| + |
| + /* Return 8bit */ |
| + cp.w r12, FFI_TYPE_UINT8 |
| + breq .Lget8 |
| + |
| + /* Return 16bit */ |
| + cp.w r12, FFI_TYPE_UINT16 |
| + breq .Lget16 |
| + |
| +1: |
| + /* Return 32bit */ |
| + cp.w r12, FFI_TYPE_UINT32 |
| + breq .Lget32 |
| + cp.w r12, FFI_TYPE_UINT16 |
| + breq .Lget32 |
| + cp.w r12, FFI_TYPE_UINT8 |
| + breq .Lget32 |
| + |
| + /* Return 64bit */ |
| + cp.w r12, FFI_TYPE_UINT64 |
| + breq .Lget64 |
| + |
| + /* Didn't match anything */ |
| + bral .Lclend |
| + |
| +.Lget64: |
| + ld.w r11, sp[0] |
| + ld.w r10, sp[4] |
| + bral .Lclend |
| + |
| +.Lget32: |
| + ld.w r12, sp[0] |
| + bral .Lclend |
| + |
| +.Lget16: |
| + ld.uh r12, sp[0] |
| + bral .Lclend |
| + |
| +.Lget8: |
| + ld.ub r12, sp[0] |
| + bral .Lclend |
| + |
| +.Lclend: |
| + sub sp, -12 |
| + ldm sp++, r0,lr |
| + sub sp, -20 |
| + mov pc, lr |
| + |
| + .size ffi_closure_SYSV, . - ffi_closure_SYSV |
| + |
| +#if defined __ELF__ && defined __linux__ |
| + .section .note.GNU-stack,"",@progbits |
| +#endif |
| Index: libffi/Makefile.am |
| =================================================================== |
| --- libffi.orig/Makefile.am |
| +++ libffi/Makefile.am |
| @@ -7,6 +7,7 @@ SUBDIRS = include testsuite man |
| EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj configure.host \ |
| src/alpha/ffi.c src/alpha/osf.S src/alpha/ffitarget.h \ |
| src/arm/ffi.c src/arm/sysv.S src/arm/ffitarget.h \ |
| + src/avr32/ffi.c src/avr32/sysv.S src/avr32/ffitarget.h \ |
| src/cris/ffi.c src/cris/sysv.S src/cris/ffitarget.h \ |
| src/ia64/ffi.c src/ia64/ffitarget.h src/ia64/ia64_flags.h \ |
| src/ia64/unix.S \ |
| @@ -141,6 +142,9 @@ endif |
| if ARM |
| nodist_libffi_la_SOURCES += src/arm/sysv.S src/arm/ffi.c |
| endif |
| +if AVR32 |
| +nodist_libffi_la_SOURCES += src/avr32/sysv.S src/avr32/ffi.c |
| +endif |
| if LIBFFI_CRIS |
| nodist_libffi_la_SOURCES += src/cris/sysv.S src/cris/ffi.c |
| endif |
| Index: libffi/configure |
| =================================================================== |
| --- libffi.orig/configure |
| +++ libffi/configure |
| @@ -813,6 +813,8 @@ FRV_FALSE |
| FRV_TRUE |
| LIBFFI_CRIS_FALSE |
| LIBFFI_CRIS_TRUE |
| +AVR32_FALSE |
| +AVR32_TRUE |
| ARM_FALSE |
| ARM_TRUE |
| POWERPC_FREEBSD_FALSE |
| @@ -4770,13 +4772,13 @@ if test "${lt_cv_nm_interface+set}" = se |
| else |
| lt_cv_nm_interface="BSD nm" |
| echo "int some_variable = 0;" > conftest.$ac_ext |
| - (eval echo "\"\$as_me:4773: $ac_compile\"" >&5) |
| + (eval echo "\"\$as_me:4775: $ac_compile\"" >&5) |
| (eval "$ac_compile" 2>conftest.err) |
| cat conftest.err >&5 |
| - (eval echo "\"\$as_me:4776: $NM \\\"conftest.$ac_objext\\\"\"" >&5) |
| + (eval echo "\"\$as_me:4778: $NM \\\"conftest.$ac_objext\\\"\"" >&5) |
| (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) |
| cat conftest.err >&5 |
| - (eval echo "\"\$as_me:4779: output\"" >&5) |
| + (eval echo "\"\$as_me:4781: output\"" >&5) |
| cat conftest.out >&5 |
| if $GREP 'External.*some_variable' conftest.out > /dev/null; then |
| lt_cv_nm_interface="MS dumpbin" |
| @@ -5982,7 +5984,7 @@ ia64-*-hpux*) |
| ;; |
| *-*-irix6*) |
| # Find out which ABI we are using. |
| - echo '#line 5985 "configure"' > conftest.$ac_ext |
| + echo '#line 5987 "configure"' > conftest.$ac_ext |
| if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 |
| (eval $ac_compile) 2>&5 |
| ac_status=$? |
| @@ -7835,11 +7837,11 @@ else |
| -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ |
| -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ |
| -e 's:$: $lt_compiler_flag:'` |
| - (eval echo "\"\$as_me:7838: $lt_compile\"" >&5) |
| + (eval echo "\"\$as_me:7840: $lt_compile\"" >&5) |
| (eval "$lt_compile" 2>conftest.err) |
| ac_status=$? |
| cat conftest.err >&5 |
| - echo "$as_me:7842: \$? = $ac_status" >&5 |
| + echo "$as_me:7844: \$? = $ac_status" >&5 |
| if (exit $ac_status) && test -s "$ac_outfile"; then |
| # The compiler can only warn and ignore the option if not recognized |
| # So say no if there are warnings other than the usual output. |
| @@ -8174,11 +8176,11 @@ else |
| -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ |
| -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ |
| -e 's:$: $lt_compiler_flag:'` |
| - (eval echo "\"\$as_me:8177: $lt_compile\"" >&5) |
| + (eval echo "\"\$as_me:8179: $lt_compile\"" >&5) |
| (eval "$lt_compile" 2>conftest.err) |
| ac_status=$? |
| cat conftest.err >&5 |
| - echo "$as_me:8181: \$? = $ac_status" >&5 |
| + echo "$as_me:8183: \$? = $ac_status" >&5 |
| if (exit $ac_status) && test -s "$ac_outfile"; then |
| # The compiler can only warn and ignore the option if not recognized |
| # So say no if there are warnings other than the usual output. |
| @@ -8279,11 +8281,11 @@ else |
| -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ |
| -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ |
| -e 's:$: $lt_compiler_flag:'` |
| - (eval echo "\"\$as_me:8282: $lt_compile\"" >&5) |
| + (eval echo "\"\$as_me:8284: $lt_compile\"" >&5) |
| (eval "$lt_compile" 2>out/conftest.err) |
| ac_status=$? |
| cat out/conftest.err >&5 |
| - echo "$as_me:8286: \$? = $ac_status" >&5 |
| + echo "$as_me:8288: \$? = $ac_status" >&5 |
| if (exit $ac_status) && test -s out/conftest2.$ac_objext |
| then |
| # The compiler can only warn and ignore the option if not recognized |
| @@ -8334,11 +8336,11 @@ else |
| -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ |
| -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ |
| -e 's:$: $lt_compiler_flag:'` |
| - (eval echo "\"\$as_me:8337: $lt_compile\"" >&5) |
| + (eval echo "\"\$as_me:8339: $lt_compile\"" >&5) |
| (eval "$lt_compile" 2>out/conftest.err) |
| ac_status=$? |
| cat out/conftest.err >&5 |
| - echo "$as_me:8341: \$? = $ac_status" >&5 |
| + echo "$as_me:8343: \$? = $ac_status" >&5 |
| if (exit $ac_status) && test -s out/conftest2.$ac_objext |
| then |
| # The compiler can only warn and ignore the option if not recognized |
| @@ -11137,7 +11139,7 @@ else |
| lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 |
| lt_status=$lt_dlunknown |
| cat > conftest.$ac_ext <<_LT_EOF |
| -#line 11140 "configure" |
| +#line 11142 "configure" |
| #include "confdefs.h" |
| |
| #if HAVE_DLFCN_H |
| @@ -11233,7 +11235,7 @@ else |
| lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 |
| lt_status=$lt_dlunknown |
| cat > conftest.$ac_ext <<_LT_EOF |
| -#line 11236 "configure" |
| +#line 11238 "configure" |
| #include "confdefs.h" |
| |
| #if HAVE_DLFCN_H |
| @@ -12155,6 +12157,10 @@ case "$host" in |
| TARGET=X86_64; TARGETDIR=x86 |
| ;; |
| |
| + avr32*-*-*) |
| + TARGET=AVR32; TARGETDIR=avr32 |
| + ;; |
| + |
| cris-*-*) |
| TARGET=LIBFFI_CRIS; TARGETDIR=cris |
| ;; |
| @@ -12391,6 +12397,14 @@ else |
| ARM_FALSE= |
| fi |
| |
| + if test x$TARGET = xAVR32; then |
| + AVR32_TRUE= |
| + AVR32_FALSE='#' |
| +else |
| + AVR32_TRUE='#' |
| + AVR32_FALSE= |
| +fi |
| + |
| if test x$TARGET = xLIBFFI_CRIS; then |
| LIBFFI_CRIS_TRUE= |
| LIBFFI_CRIS_FALSE='#' |
| @@ -14483,6 +14497,16 @@ _ACEOF |
| fi |
| fi |
| |
| +case "$target" in |
| + i?86-apple-darwin10*) |
| + |
| +cat >>confdefs.h <<\_ACEOF |
| +#define FFI_MMAP_EXEC_WRIT 1 |
| +_ACEOF |
| + |
| + ;; |
| +esac |
| + |
| { $as_echo "$as_me:$LINENO: checking whether .eh_frame section should be read-only" >&5 |
| $as_echo_n "checking whether .eh_frame section should be read-only... " >&6; } |
| if test "${libffi_cv_ro_eh_frame+set}" = set; then |
| @@ -14895,6 +14919,13 @@ $as_echo "$as_me: error: conditional \"A |
| Usually this means the macro was only invoked conditionally." >&2;} |
| { (exit 1); exit 1; }; } |
| fi |
| +if test -z "${AVR32_TRUE}" && test -z "${AVR32_FALSE}"; then |
| + { { $as_echo "$as_me:$LINENO: error: conditional \"AVR32\" was never defined. |
| +Usually this means the macro was only invoked conditionally." >&5 |
| +$as_echo "$as_me: error: conditional \"AVR32\" was never defined. |
| +Usually this means the macro was only invoked conditionally." >&2;} |
| + { (exit 1); exit 1; }; } |
| +fi |
| if test -z "${LIBFFI_CRIS_TRUE}" && test -z "${LIBFFI_CRIS_FALSE}"; then |
| { { $as_echo "$as_me:$LINENO: error: conditional \"LIBFFI_CRIS\" was never defined. |
| Usually this means the macro was only invoked conditionally." >&5 |
| Index: libffi/configure.ac |
| =================================================================== |
| --- libffi.orig/configure.ac |
| +++ libffi/configure.ac |
| @@ -58,6 +58,10 @@ case "$host" in |
| TARGET=X86_64; TARGETDIR=x86 |
| ;; |
| |
| + avr32*-*-*) |
| + TARGET=AVR32; TARGETDIR=avr32 |
| + ;; |
| + |
| cris-*-*) |
| TARGET=LIBFFI_CRIS; TARGETDIR=cris |
| ;; |
| @@ -180,6 +184,7 @@ AM_CONDITIONAL(POWERPC_AIX, test x$TARGE |
| AM_CONDITIONAL(POWERPC_DARWIN, test x$TARGET = xPOWERPC_DARWIN) |
| AM_CONDITIONAL(POWERPC_FREEBSD, test x$TARGET = xPOWERPC_FREEBSD) |
| AM_CONDITIONAL(ARM, test x$TARGET = xARM) |
| +AM_CONDITIONAL(AVR32, test x$TARGET = xAVR32) |
| AM_CONDITIONAL(LIBFFI_CRIS, test x$TARGET = xLIBFFI_CRIS) |
| AM_CONDITIONAL(FRV, test x$TARGET = xFRV) |
| AM_CONDITIONAL(S390, test x$TARGET = xS390) |
| Index: libffi/ChangeLog.libffi |
| =================================================================== |
| --- libffi.orig/ChangeLog.libffi |
| +++ libffi/ChangeLog.libffi |
| @@ -1,3 +1,14 @@ |
| +2009-10-05 Bradley Smith <brad@brad-smith.co.uk> |
| + |
| + * configure.ac, Makefile.am, src/avr32/ffi.c, |
| + src/avr32/ffitarget.h, |
| + src/avr32/sysv.S: Add AVR32 port. |
| + * testsuite/libffi.call/cls_dbls_struct.c, |
| + testsuite/libffi.call/cls_double_va.c, |
| + testsuite/libffi.call/cls_longdouble_va.c, |
| + testsuite/libffi.call/huge_struct.c: Mark expected failures on |
| + AVR32. |
| + |
| 2009-06-16 Andrew Haley <aph@redhat.com> |
| |
| * testsuite/libffi.call/cls_align_sint64.c, |