[multiple changes]
authorAndrew Haley <aph@gcc.gnu.org>
Tue, 4 Sep 2007 17:52:45 +0000 (17:52 +0000)
committerAndrew Haley <aph@gcc.gnu.org>
Tue, 4 Sep 2007 17:52:45 +0000 (17:52 +0000)
2007-09-04    <aph@redhat.com>

* 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  <s_j_newbury@yahoo.co.uk>

* src/arm/ffi.c (FFI_INIT_TRAMPOLINE): Use __clear_cache instead of
directly using the sys_cacheflush syscall.

2007-07-27  Andrew Haley  <aph@redhat.com>

* src/arm/sysv.S (ffi_closure_SYSV): Add soft-float.

From-SVN: r128093

libffi/ChangeLog
libffi/src/arm/ffi.c
libffi/src/arm/sysv.S

index 5ea8207e081ab33b981165d5b28f209e1a16fd64..0f434c862762c8ebb17df50c5d753643741e0f03 100644 (file)
@@ -1,3 +1,28 @@
+2007-09-04    <aph@redhat.com>
+
+       * 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  <s_j_newbury@yahoo.co.uk>
+
+       * src/arm/ffi.c (FFI_INIT_TRAMPOLINE): Use __clear_cache instead of 
+       directly using the sys_cacheflush syscall.
+
+2007-07-27  Andrew Haley  <aph@redhat.com>
+
+       * src/arm/sysv.S (ffi_closure_SYSV): Add soft-float.
+
 2007-09-03  Maciej W. Rozycki  <macro@linux-mips.org>
 
        * Makefile.am: Unify MIPS_IRIX and MIPS_LINUX into MIPS.
index f3cd50653e4419d1e50d88f185088e8160d0606a..35b2c3477a485f1425c7ba27bc689decc707befc 100644 (file)
@@ -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]));                       \
  })
 
 
index 00f43b2000bac415b07145de994467736de30550..12876d1205435f6348e24a0c1ff186b44f5903bb 100644 (file)
 # 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
        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)