d8d9cbe
2007-09-04  Andrew Haley  <aph@redhat.com>
d8d9cbe
d8d9cbe
	* src/arm/sysv.S (UNWIND): New.
d8d9cbe
	(Whole file): Conditionally compile unwinder directives.
d8d9cbe
	* src/arm/sysv.S: Add unwinder directives.
d8d9cbe
d8d9cbe
	* src/arm/ffi.c (ffi_prep_args): Align structs by at least 4 bytes.
d8d9cbe
	Only treat r0 as a struct address if we're actually returning a
d8d9cbe
	struct by address.
d8d9cbe
	Only copy the bytes that are actually within a struct.
d8d9cbe
	(ffi_prep_cif_machdep): A Composite Type not larger than 4 bytes
d8d9cbe
	is returned in r0, not passed by address.
d8d9cbe
	(ffi_call): Allocate a word-sized temporary for the case where
d8d9cbe
	a composite is returned in r0.
d8d9cbe
	(ffi_prep_incoming_args_SYSV): Align as necessary.
d8d9cbe
d8d9cbe
2007-08-05  Steven Newbury  <s_j_newbury@yahoo.co.uk>
d8d9cbe
d8d9cbe
	* src/arm/ffi.c (FFI_INIT_TRAMPOLINE): Use __clear_cache instead of 
d8d9cbe
	directly using the sys_cacheflush syscall.
d8d9cbe
d8d9cbe
2007-07-27  Andrew Haley  <aph@redhat.com>
d8d9cbe
d8d9cbe
	* src/arm/sysv.S (ffi_closure_SYSV): Add soft-float.
d8d9cbe
d8d9cbe
--- libffi/src/arm/ffi.c	(revision 128092)
d8d9cbe
+++ libffi/src/arm/ffi.c	(revision 128093)
d8d9cbe
@@ -40,7 +40,7 @@ void ffi_prep_args(char *stack, extended
d8d9cbe
 
d8d9cbe
   argp = stack;
d8d9cbe
 
d8d9cbe
-  if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) {
d8d9cbe
+  if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
d8d9cbe
     *(void **) argp = ecif->rvalue;
d8d9cbe
     argp += 4;
d8d9cbe
   }
d8d9cbe
@@ -58,6 +58,9 @@ void ffi_prep_args(char *stack, extended
d8d9cbe
 	argp = (char *) ALIGN(argp, (*p_arg)->alignment);
d8d9cbe
       }
d8d9cbe
 
d8d9cbe
+      if ((*p_arg)->type == FFI_TYPE_STRUCT)
d8d9cbe
+	argp = (char *) ALIGN(argp, 4);
d8d9cbe
+
d8d9cbe
 	  z = (*p_arg)->size;
d8d9cbe
 	  if (z < sizeof(int))
d8d9cbe
 	    {
d8d9cbe
@@ -81,7 +84,7 @@ void ffi_prep_args(char *stack, extended
d8d9cbe
 		  break;
d8d9cbe
 		  
d8d9cbe
 		case FFI_TYPE_STRUCT:
d8d9cbe
-		  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
d8d9cbe
+		  memcpy(argp, *p_argv, (*p_arg)->size);
d8d9cbe
 		  break;
d8d9cbe
 
d8d9cbe
 		default:
d8d9cbe
@@ -115,7 +118,6 @@ ffi_status ffi_prep_cif_machdep(ffi_cif 
d8d9cbe
   switch (cif->rtype->type)
d8d9cbe
     {
d8d9cbe
     case FFI_TYPE_VOID:
d8d9cbe
-    case FFI_TYPE_STRUCT:
d8d9cbe
     case FFI_TYPE_FLOAT:
d8d9cbe
     case FFI_TYPE_DOUBLE:
d8d9cbe
       cif->flags = (unsigned) cif->rtype->type;
d8d9cbe
@@ -126,6 +128,17 @@ ffi_status ffi_prep_cif_machdep(ffi_cif 
d8d9cbe
       cif->flags = (unsigned) FFI_TYPE_SINT64;
d8d9cbe
       break;
d8d9cbe
 
d8d9cbe
+    case FFI_TYPE_STRUCT:
d8d9cbe
+      if (cif->rtype->size <= 4)
d8d9cbe
+	/* A Composite Type not larger than 4 bytes is returned in r0.  */
d8d9cbe
+	cif->flags = (unsigned)FFI_TYPE_INT;
d8d9cbe
+      else
d8d9cbe
+	/* A Composite Type larger than 4 bytes, or whose size cannot
d8d9cbe
+	   be determined statically ... is stored in memory at an
d8d9cbe
+	   address passed [in r0].  */
d8d9cbe
+	cif->flags = (unsigned)FFI_TYPE_STRUCT;
d8d9cbe
+      break;
d8d9cbe
+
d8d9cbe
     default:
d8d9cbe
       cif->flags = FFI_TYPE_INT;
d8d9cbe
       break;
d8d9cbe
@@ -141,21 +154,27 @@ void ffi_call(ffi_cif *cif, void (*fn)()
d8d9cbe
 {
d8d9cbe
   extended_cif ecif;
d8d9cbe
 
d8d9cbe
+  int small_struct = (cif->flags == FFI_TYPE_INT 
d8d9cbe
+		      && cif->rtype->type == FFI_TYPE_STRUCT);
d8d9cbe
+
d8d9cbe
   ecif.cif = cif;
d8d9cbe
   ecif.avalue = avalue;
d8d9cbe
+
d8d9cbe
+  unsigned int temp;
d8d9cbe
   
d8d9cbe
   /* If the return value is a struct and we don't have a return	*/
d8d9cbe
   /* value address then we need to make one		        */
d8d9cbe
 
d8d9cbe
   if ((rvalue == NULL) && 
d8d9cbe
-      (cif->rtype->type == FFI_TYPE_STRUCT))
d8d9cbe
+      (cif->flags == FFI_TYPE_STRUCT))
d8d9cbe
     {
d8d9cbe
       ecif.rvalue = alloca(cif->rtype->size);
d8d9cbe
     }
d8d9cbe
+  else if (small_struct)
d8d9cbe
+    ecif.rvalue = &tem;;
d8d9cbe
   else
d8d9cbe
     ecif.rvalue = rvalue;
d8d9cbe
-    
d8d9cbe
-  
d8d9cbe
+
d8d9cbe
   switch (cif->abi) 
d8d9cbe
     {
d8d9cbe
     case FFI_SYSV:
d8d9cbe
@@ -167,6 +186,8 @@ void ffi_call(ffi_cif *cif, void (*fn)()
d8d9cbe
       FFI_ASSERT(0);
d8d9cbe
       break;
d8d9cbe
     }
d8d9cbe
+  if (small_struct)
d8d9cbe
+    memcpy (rvalue, &temp, cif->rtype->size);
d8d9cbe
 }
d8d9cbe
 
d8d9cbe
 /** private members **/
d8d9cbe
@@ -228,9 +249,12 @@ ffi_prep_incoming_args_SYSV(char *stack,
d8d9cbe
     {
d8d9cbe
       size_t z;
d8d9cbe
 
d8d9cbe
+      size_t alignment = (*p_arg)->alignment;
d8d9cbe
+      if (alignment < 4)
d8d9cbe
+	alignment = 4;
d8d9cbe
       /* Align if necessary */
d8d9cbe
-      if ((sizeof(int) - 1) & (unsigned) argp) {
d8d9cbe
-	argp = (char *) ALIGN(argp, sizeof(int));
d8d9cbe
+      if ((alignment - 1) & (unsigned) argp) {
d8d9cbe
+	argp = (char *) ALIGN(argp, alignment);
d8d9cbe
       }
d8d9cbe
 
d8d9cbe
       z = (*p_arg)->size;
d8d9cbe
@@ -248,21 +272,16 @@ ffi_prep_incoming_args_SYSV(char *stack,
d8d9cbe
 
d8d9cbe
 /* How to make a trampoline.  */
d8d9cbe
 
d8d9cbe
-#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
d8d9cbe
-({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
d8d9cbe
-   unsigned int  __fun = (unsigned int)(FUN); \
d8d9cbe
-   unsigned int  __ctx = (unsigned int)(CTX); \
d8d9cbe
+#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX)				\
d8d9cbe
+({ unsigned char *__tramp = (unsigned char*)(TRAMP);			\
d8d9cbe
+   unsigned int  __fun = (unsigned int)(FUN);				\
d8d9cbe
+   unsigned int  __ctx = (unsigned int)(CTX);				\
d8d9cbe
    *(unsigned int*) &__tramp[0] = 0xe92d000f; /* stmfd sp!, {r0-r3} */	\
d8d9cbe
-   *(unsigned int*) &__tramp[4] = 0xe59f0000; /* ldr r0, [pc] */ \
d8d9cbe
-   *(unsigned int*) &__tramp[8] = 0xe59ff000; /* ldr pc, [pc] */ \
d8d9cbe
-   *(unsigned int*) &__tramp[12] = __ctx; \
d8d9cbe
-   *(unsigned int*) &__tramp[16] = __fun; \
d8d9cbe
-   register unsigned long _beg __asm ("a1") = (unsigned long) (&__tramp[0]);	\
d8d9cbe
-   register unsigned long _end __asm ("a2") = (unsigned long) (&__tramp[19]);	\
d8d9cbe
-   register unsigned long _flg __asm ("a3") = 0;			\
d8d9cbe
-   __asm __volatile ("swi 0x9f0002		@ sys_cacheflush"	\
d8d9cbe
-	   		    : "=r" (_beg)				\
d8d9cbe
-	   		    : "0" (_beg), "r" (_end), "r" (_flg));	\
d8d9cbe
+   *(unsigned int*) &__tramp[4] = 0xe59f0000; /* ldr r0, [pc] */	\
d8d9cbe
+   *(unsigned int*) &__tramp[8] = 0xe59ff000; /* ldr pc, [pc] */	\
d8d9cbe
+   *(unsigned int*) &__tramp[12] = __ctx;				\
d8d9cbe
+   *(unsigned int*) &__tramp[16] = __fun;				\
d8d9cbe
+   __clear_cache((&__tramp[0]), (&__tramp[19]));			\
d8d9cbe
  })
d8d9cbe
 
d8d9cbe
 
d8d9cbe
--- libffi/src/arm/sysv.S	(revision 128092)
d8d9cbe
+++ libffi/src/arm/sysv.S	(revision 128093)
d8d9cbe
@@ -82,6 +82,14 @@
d8d9cbe
 # define call_reg(x)	mov	lr, pc ; mov	pc, x
d8d9cbe
 #endif
d8d9cbe
 
d8d9cbe
+/* Conditionally compile unwinder directives.  */
d8d9cbe
+#ifdef __ARM_EABI__
d8d9cbe
+#define UNWIND
d8d9cbe
+#else
d8d9cbe
+#define UNWIND @
d8d9cbe
+#endif	
d8d9cbe
+
d8d9cbe
+	
d8d9cbe
 #if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
d8d9cbe
 .macro	ARM_FUNC_START name
d8d9cbe
 	.text
d8d9cbe
@@ -92,6 +100,7 @@
d8d9cbe
 	bx	pc
d8d9cbe
 	nop
d8d9cbe
 	.arm
d8d9cbe
+	UNWIND .fnstart
d8d9cbe
 /* A hook to tell gdb that we've switched to ARM mode.  Also used to call
d8d9cbe
    directly from other local arm routines.  */
d8d9cbe
 _L__\name:		
d8d9cbe
@@ -102,6 +111,7 @@ _L__\name:		
d8d9cbe
 	.align 0
d8d9cbe
 	.arm
d8d9cbe
 	ENTRY(\name)
d8d9cbe
+	UNWIND .fnstart
d8d9cbe
 .endm
d8d9cbe
 #endif
d8d9cbe
 
d8d9cbe
@@ -134,8 +144,11 @@ _L__\name:		
d8d9cbe
 ARM_FUNC_START ffi_call_SYSV
d8d9cbe
 	@ Save registers
d8d9cbe
         stmfd	sp!, {r0-r3, fp, lr}
d8d9cbe
+	UNWIND .save	{r0-r3, fp, lr}
d8d9cbe
 	mov	fp, sp
d8d9cbe
 
d8d9cbe
+	UNWIND .setfp	fp, sp
d8d9cbe
+
d8d9cbe
 	@ Make room for all of the new args.
d8d9cbe
 	sub	sp, fp, r2
d8d9cbe
 
d8d9cbe
@@ -205,6 +218,7 @@ LSYM(Lepilogue):
d8d9cbe
 	RETLDM	"r0-r3,fp"
d8d9cbe
 
d8d9cbe
 .ffi_call_SYSV_end:
d8d9cbe
+	UNWIND .fnend
d8d9cbe
         .size    CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
d8d9cbe
 
d8d9cbe
 /*
d8d9cbe
@@ -216,21 +230,40 @@ LSYM(Lepilogue):
d8d9cbe
 */
d8d9cbe
 
d8d9cbe
 ARM_FUNC_START ffi_closure_SYSV
d8d9cbe
+	UNWIND .pad #16
d8d9cbe
 	add	ip, sp, #16
d8d9cbe
 	stmfd	sp!, {ip, lr}
d8d9cbe
+	UNWIND .save	{r0, lr}
d8d9cbe
 	add	r2, sp, #8
d8d9cbe
+	.pad #16
d8d9cbe
 	sub	sp, sp, #16
d8d9cbe
 	str	sp, [sp, #8]
d8d9cbe
 	add	r1, sp, #8
d8d9cbe
 	bl	ffi_closure_SYSV_inner
d8d9cbe
 	cmp	r0, #FFI_TYPE_INT
d8d9cbe
 	beq	.Lretint
d8d9cbe
+
d8d9cbe
 	cmp	r0, #FFI_TYPE_FLOAT
d8d9cbe
+#ifdef __SOFTFP__
d8d9cbe
+	beq	.Lretint
d8d9cbe
+#else
d8d9cbe
 	beq	.Lretfloat
d8d9cbe
+#endif
d8d9cbe
+
d8d9cbe
 	cmp	r0, #FFI_TYPE_DOUBLE
d8d9cbe
+#ifdef __SOFTFP__
d8d9cbe
+	beq	.Lretlonglong
d8d9cbe
+#else
d8d9cbe
 	beq	.Lretdouble
d8d9cbe
+#endif
d8d9cbe
+
d8d9cbe
 	cmp	r0, #FFI_TYPE_LONGDOUBLE
d8d9cbe
+#ifdef __SOFTFP__
d8d9cbe
+	beq	.Lretlonglong
d8d9cbe
+#else
d8d9cbe
 	beq	.Lretlongdouble
d8d9cbe
+#endif
d8d9cbe
+
d8d9cbe
 	cmp	r0, #FFI_TYPE_SINT64
d8d9cbe
 	beq	.Lretlonglong
d8d9cbe
 .Lclosure_epilogue:
d8d9cbe
@@ -243,6 +276,8 @@ ARM_FUNC_START ffi_closure_SYSV
d8d9cbe
 	ldr	r0, [sp]
d8d9cbe
 	ldr	r1, [sp, #4]
d8d9cbe
 	b	.Lclosure_epilogue
d8d9cbe
+
d8d9cbe
+#ifndef __SOFTFP__
d8d9cbe
 .Lretfloat:
d8d9cbe
 	ldfs	f0, [sp]
d8d9cbe
 	b	.Lclosure_epilogue
d8d9cbe
@@ -252,6 +287,9 @@ ARM_FUNC_START ffi_closure_SYSV
d8d9cbe
 .Lretlongdouble:
d8d9cbe
 	ldfd	f0, [sp]
d8d9cbe
 	b	.Lclosure_epilogue
d8d9cbe
+#endif
d8d9cbe
+
d8d9cbe
 .ffi_closure_SYSV_end:
d8d9cbe
+	UNWIND .fnend
d8d9cbe
         .size    CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
d8d9cbe