Commit b5296e52 by Roman Zippel Committed by Roman Zippel

ffi.c (ffi_prep_args,ffi_prep_cif_machdep): Fix numerous test suite failures.

	* src/m68k/ffi.c (ffi_prep_args,ffi_prep_cif_machdep): Fix
	numerous test suite failures.
	* src/m68k/sysv.S (ffi_call_SYSV): Likewise.

From-SVN: r124599
parent 8b42b2fb
2007-05-10 Roman Zippel <zippel@linux-m68k.org>
* src/m68k/ffi.c (ffi_prep_args,ffi_prep_cif_machdep): Fix
numerous test suite failures.
* src/m68k/sysv.S (ffi_call_SYSV): Likewise.
2007-04-11 Paolo Bonzini <bonzini@gnu.org> 2007-04-11 Paolo Bonzini <bonzini@gnu.org>
* Makefile.am (EXTRA_DIST): Bring up to date. * Makefile.am (EXTRA_DIST): Bring up to date.
......
...@@ -9,10 +9,15 @@ ...@@ -9,10 +9,15 @@
#include <stdlib.h> #include <stdlib.h>
void ffi_call_SYSV (extended_cif *,
unsigned, unsigned,
void *, void (*fn) ());
void *ffi_prep_args (void *stack, extended_cif *ecif);
/* ffi_prep_args is called by the assembly routine once stack space has /* ffi_prep_args is called by the assembly routine once stack space has
been allocated for the function's arguments. */ been allocated for the function's arguments. */
static void * void *
ffi_prep_args (void *stack, extended_cif *ecif) ffi_prep_args (void *stack, extended_cif *ecif)
{ {
unsigned int i; unsigned int i;
...@@ -24,7 +29,7 @@ ffi_prep_args (void *stack, extended_cif *ecif) ...@@ -24,7 +29,7 @@ ffi_prep_args (void *stack, extended_cif *ecif)
argp = stack; argp = stack;
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
&& ecif->cif->rtype->size > 8) && !ecif->cif->flags)
struct_value_ptr = ecif->rvalue; struct_value_ptr = ecif->rvalue;
else else
struct_value_ptr = NULL; struct_value_ptr = NULL;
...@@ -37,44 +42,47 @@ ffi_prep_args (void *stack, extended_cif *ecif) ...@@ -37,44 +42,47 @@ ffi_prep_args (void *stack, extended_cif *ecif)
{ {
size_t z; size_t z;
/* Align if necessary. */ z = (*p_arg)->size;
if (((*p_arg)->alignment - 1) & (unsigned) argp) if (z < sizeof (int))
argp = (char *) ALIGN (argp, (*p_arg)->alignment); {
switch ((*p_arg)->type)
z = (*p_arg)->size;
if (z < sizeof (int))
{ {
switch ((*p_arg)->type) case FFI_TYPE_SINT8:
{ *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
case FFI_TYPE_SINT8: break;
*(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
break; case FFI_TYPE_UINT8:
*(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
case FFI_TYPE_UINT8: break;
*(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
break; case FFI_TYPE_SINT16:
*(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
case FFI_TYPE_SINT16: break;
*(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
break; case FFI_TYPE_UINT16:
*(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
case FFI_TYPE_UINT16: break;
*(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
break; case FFI_TYPE_STRUCT:
memcpy (argp + sizeof (int) - z, *p_argv, z);
case FFI_TYPE_STRUCT: break;
memcpy (argp + sizeof (int) - z, *p_argv, z);
break; default:
FFI_ASSERT (0);
default:
FFI_ASSERT (0);
}
z = sizeof (int);
} }
else z = sizeof (int);
memcpy (argp, *p_argv, z); }
p_argv++; else
argp += z; {
memcpy (argp, *p_argv, z);
/* Align if necessary. */
if ((sizeof(int) - 1) & z)
z = ALIGN(z, sizeof(int));
}
p_argv++;
argp += z;
} }
return struct_value_ptr; return struct_value_ptr;
...@@ -86,7 +94,8 @@ ffi_prep_args (void *stack, extended_cif *ecif) ...@@ -86,7 +94,8 @@ ffi_prep_args (void *stack, extended_cif *ecif)
#define CIF_FLAGS_DOUBLE 8 #define CIF_FLAGS_DOUBLE 8
#define CIF_FLAGS_LDOUBLE 16 #define CIF_FLAGS_LDOUBLE 16
#define CIF_FLAGS_POINTER 32 #define CIF_FLAGS_POINTER 32
#define CIF_FLAGS_STRUCT 64 #define CIF_FLAGS_STRUCT1 64
#define CIF_FLAGS_STRUCT2 128
/* Perform machine dependent cif processing */ /* Perform machine dependent cif processing */
ffi_status ffi_status
...@@ -100,12 +109,24 @@ ffi_prep_cif_machdep (ffi_cif *cif) ...@@ -100,12 +109,24 @@ ffi_prep_cif_machdep (ffi_cif *cif)
break; break;
case FFI_TYPE_STRUCT: case FFI_TYPE_STRUCT:
if (cif->rtype->size > 4 && cif->rtype->size <= 8) switch (cif->rtype->size)
cif->flags = CIF_FLAGS_DINT; {
else if (cif->rtype->size <= 4) case 1:
cif->flags = CIF_FLAGS_STRUCT; cif->flags = CIF_FLAGS_STRUCT1;
else break;
cif->flags = 0; case 2:
cif->flags = CIF_FLAGS_STRUCT2;
break;
case 4:
cif->flags = CIF_FLAGS_INT;
break;
case 8:
cif->flags = CIF_FLAGS_DINT;
break;
default:
cif->flags = 0;
break;
}
break; break;
case FFI_TYPE_FLOAT: case FFI_TYPE_FLOAT:
...@@ -137,11 +158,6 @@ ffi_prep_cif_machdep (ffi_cif *cif) ...@@ -137,11 +158,6 @@ ffi_prep_cif_machdep (ffi_cif *cif)
return FFI_OK; return FFI_OK;
} }
extern void ffi_call_SYSV (void *(*) (void *, extended_cif *),
extended_cif *,
unsigned, unsigned, unsigned,
void *, void (*fn) ());
void void
ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue) ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
{ {
...@@ -149,7 +165,7 @@ ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue) ...@@ -149,7 +165,7 @@ ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
ecif.cif = cif; ecif.cif = cif;
ecif.avalue = avalue; ecif.avalue = avalue;
/* If the return value is a struct and we don't have a return value /* If the return value is a struct and we don't have a return value
address then we need to make one. */ address then we need to make one. */
...@@ -159,13 +175,11 @@ ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue) ...@@ -159,13 +175,11 @@ ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
ecif.rvalue = alloca (cif->rtype->size); ecif.rvalue = alloca (cif->rtype->size);
else else
ecif.rvalue = rvalue; ecif.rvalue = rvalue;
switch (cif->abi)
switch (cif->abi)
{ {
case FFI_SYSV: case FFI_SYSV:
ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes, ffi_call_SYSV (&ecif, cif->bytes, cif->flags,
cif->flags, cif->rtype->size * 8,
ecif.rvalue, fn); ecif.rvalue, fn);
break; break;
......
...@@ -12,36 +12,40 @@ ...@@ -12,36 +12,40 @@
.globl ffi_call_SYSV .globl ffi_call_SYSV
.type ffi_call_SYSV,@function .type ffi_call_SYSV,@function
.align 4
ffi_call_SYSV: ffi_call_SYSV:
link %fp,#0 link %fp,#0
move.l %d2,-(%sp) move.l %d2,-(%sp)
| Make room for all of the new args. | Make room for all of the new args.
sub.l 16(%fp),%sp sub.l 12(%fp),%sp
| Call ffi_prep_args | Call ffi_prep_args
move.l 12(%fp),-(%sp) move.l 8(%fp),-(%sp)
pea 4(%sp) pea 4(%sp)
move.l 8(%fp),%a0 #if !defined __PIC__
jsr (%a0) jsr ffi_prep_args
#else
bsr.l ffi_prep_args@PLTPC
#endif
addq.l #8,%sp addq.l #8,%sp
| Pass pointer to struct value, if any | Pass pointer to struct value, if any
move.l %a0,%a1 move.l %a0,%a1
| Call the function | Call the function
move.l 32(%fp),%a0 move.l 24(%fp),%a0
jsr (%a0) jsr (%a0)
| Remove the space we pushed for the args | Remove the space we pushed for the args
add.l 16(%fp),%sp add.l 12(%fp),%sp
| Load the pointer to storage for the return value | Load the pointer to storage for the return value
move.l 28(%fp),%a1 move.l 20(%fp),%a1
| Load the return type code | Load the return type code
move.l 20(%fp),%d2 move.l 16(%fp),%d2
| If the return value pointer is NULL, assume no return value. | If the return value pointer is NULL, assume no return value.
tst.l %a1 tst.l %a1
...@@ -79,19 +83,24 @@ retlongdouble: ...@@ -79,19 +83,24 @@ retlongdouble:
retpointer: retpointer:
btst #5,%d2 btst #5,%d2
jbeq retstruct jbeq retstruct1
move.l %a0,(%a1) move.l %a0,(%a1)
jbra epilogue jbra epilogue
retstruct: retstruct1:
btst #6,%d2 btst #6,%d2
jbeq retstruct2
move.b %d0,(%a1)
jbra epilogue
retstruct2:
btst #7,%d2
jbeq noretval jbeq noretval
move.l 24(%fp),%d2 move.w %d0,(%a1)
bfins %d0,(%a1){#0,%d2}
noretval: noretval:
epilogue: epilogue:
move.l (%sp)+,%d2 move.l (%sp)+,%d2
unlk %a6 unlk %fp
rts rts
.size ffi_call_SYSV,.-ffi_call_SYSV .size ffi_call_SYSV,.-ffi_call_SYSV
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment