Many many updates. Merge from gcc and then some.
This commit is contained in:
@@ -27,6 +27,7 @@ TARGET_SRC_ALPHA = alpha/ffi.c alpha/osf.S
|
||||
TARGET_SRC_M68K = m68k/ffi.c m68k/sysv.S
|
||||
TARGET_SRC_POWERPC = powerpc/ffi.c powerpc/sysv.S
|
||||
TARGET_SRC_ARM = arm/sysv.S arm/ffi.c
|
||||
TARGET_SRC_S390 = s390/sysv.S s390/ffi.c
|
||||
|
||||
##libffi_la_SOURCES = debug.c prep_cif.c types.c $(TARGET_SRC_@TARGET@)
|
||||
## Work around automake deficiency
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
Alpha Foreign Function Interface
|
||||
|
||||
$Id: ffi.c,v 1.1 1998/11/29 16:48:16 green Exp $
|
||||
|
||||
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
|
||||
@@ -30,131 +28,25 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
has been allocated for the function's arguments */
|
||||
extern void ffi_call_osf(void *, unsigned long, unsigned, void *, void (*)());
|
||||
extern void ffi_closure_osf(void);
|
||||
|
||||
static void
|
||||
ffi_prep_args(char *stack, extended_cif *ecif, int bytes, int flags)
|
||||
{
|
||||
register long i, avn;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
|
||||
/* To streamline things in the assembly code, we always allocate 12
|
||||
words for loading up the int and fp argument registers. The layout
|
||||
is as when processing varargs: the 6 fp args, the 6 int args, then
|
||||
the incoming stack. ARGP points to the first int slot. */
|
||||
argp = stack + 6 * SIZEOF_ARG;
|
||||
memset (stack, 0, 12 * SIZEOF_ARG);
|
||||
|
||||
if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT )
|
||||
{
|
||||
*(void **) argp = ecif->rvalue;
|
||||
argp += sizeof(void *);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
avn = ecif->cif->nargs;
|
||||
p_arg = ecif->cif->arg_types;
|
||||
p_argv = ecif->avalue;
|
||||
while (i < avn)
|
||||
{
|
||||
size_t z = ALIGN((*p_arg)->size, SIZEOF_ARG);
|
||||
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(SINT64 *) argp = *(SINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(UINT64 *) argp = *(UINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(SINT64 *) argp = *(SINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(UINT64 *) argp = *(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
*(SINT64 *) argp = *(SINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
*(UINT64 *) argp = *(UINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_POINTER:
|
||||
*(UINT64 *) argp = *(UINT64 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (argp - stack < 12 * SIZEOF_ARG)
|
||||
{
|
||||
/* Note the conversion -- all the fp regs are loaded as
|
||||
doubles. The in-register format is the same. */
|
||||
*(double *) (argp - 6 * SIZEOF_ARG) = *(float *)(* p_argv);
|
||||
}
|
||||
else
|
||||
*(float *) argp = *(float *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
if (argp - stack < 12 * SIZEOF_ARG)
|
||||
*(double *) (argp - 6 * SIZEOF_ARG) = *(double *)(* p_argv);
|
||||
else
|
||||
*(double *) argp = *(double *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
memcpy(argp, *p_argv, (*p_arg)->size);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
|
||||
argp += z;
|
||||
i++, p_arg++, p_argv++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
/* Adjust cif->bytes. to include 12 words for the temporary register
|
||||
argument loading area. This will be removed before the call. */
|
||||
|
||||
cif->bytes += 6*SIZEOF_ARG;
|
||||
if (cif->bytes < 12*SIZEOF_ARG)
|
||||
cif->bytes = 12*SIZEOF_ARG;
|
||||
|
||||
/* The stack must be double word aligned, so round bytes up
|
||||
appropriately. */
|
||||
|
||||
cif->bytes = ALIGN(cif->bytes, 2*sizeof(void*));
|
||||
/* Adjust cif->bytes to represent a minimum 6 words for the temporary
|
||||
register argument loading area. */
|
||||
if (cif->bytes < 6*SIZEOF_ARG)
|
||||
cif->bytes = 6*SIZEOF_ARG;
|
||||
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_STRUCT:
|
||||
cif->flags = cif->rtype->type;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
cif->flags = FFI_TYPE_FLOAT;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags = FFI_TYPE_DOUBLE;
|
||||
cif->flags = cif->rtype->type;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -165,35 +57,191 @@ ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern int ffi_call_osf(void (*)(char *, extended_cif *, int, int),
|
||||
extended_cif *, unsigned,
|
||||
unsigned, unsigned *, void (*)());
|
||||
|
||||
void
|
||||
ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
unsigned long *stack, *argp;
|
||||
long i, avn;
|
||||
ffi_type **arg_types;
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_OSF);
|
||||
|
||||
/* 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)
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_OSF:
|
||||
ffi_call_osf(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, rvalue, fn);
|
||||
break;
|
||||
if (rvalue == NULL && cif->flags == FFI_TYPE_STRUCT)
|
||||
rvalue = alloca(cif->rtype->size);
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
/* Allocate the space for the arguments, plus 4 words of temp
|
||||
space for ffi_call_osf. */
|
||||
argp = stack = alloca(cif->bytes + 4*SIZEOF_ARG);
|
||||
|
||||
if (cif->flags == FFI_TYPE_STRUCT)
|
||||
*(void **) argp++ = rvalue;
|
||||
|
||||
i = 0;
|
||||
avn = cif->nargs;
|
||||
arg_types = cif->arg_types;
|
||||
|
||||
while (i < avn)
|
||||
{
|
||||
switch ((*arg_types)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(SINT64 *) argp = *(SINT8 *)(* avalue);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(SINT64 *) argp = *(UINT8 *)(* avalue);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(SINT64 *) argp = *(SINT16 *)(* avalue);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(SINT64 *) argp = *(UINT16 *)(* avalue);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
/* Note that unsigned 32-bit quantities are sign extended. */
|
||||
*(SINT64 *) argp = *(SINT32 *)(* avalue);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_POINTER:
|
||||
*(UINT64 *) argp = *(UINT64 *)(* avalue);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (argp - stack < 6)
|
||||
{
|
||||
/* Note the conversion -- all the fp regs are loaded as
|
||||
doubles. The in-register format is the same. */
|
||||
*(double *) argp = *(float *)(* avalue);
|
||||
}
|
||||
else
|
||||
*(float *) argp = *(float *)(* avalue);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
*(double *) argp = *(double *)(* avalue);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
memcpy(argp, *avalue, (*arg_types)->size);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
|
||||
argp += ALIGN((*arg_types)->size, SIZEOF_ARG) / SIZEOF_ARG;
|
||||
i++, arg_types++, avalue++;
|
||||
}
|
||||
|
||||
ffi_call_osf(stack, cif->bytes, cif->flags, rvalue, fn);
|
||||
}
|
||||
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data)
|
||||
{
|
||||
unsigned int *tramp;
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_OSF);
|
||||
|
||||
tramp = (unsigned int *) &closure->tramp[0];
|
||||
tramp[0] = 0x47fb0401; /* mov $27,$1 */
|
||||
tramp[1] = 0xa77b0010; /* ldq $27,16($27) */
|
||||
tramp[2] = 0x6bfb0000; /* jmp $31,($27),0 */
|
||||
tramp[3] = 0x47ff041f; /* nop */
|
||||
*(void **) &tramp[4] = ffi_closure_osf;
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
/* Flush the Icache. */
|
||||
asm volatile ("imb" : : : "memory");
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
int
|
||||
ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
void **avalue;
|
||||
ffi_type **arg_types;
|
||||
long i, avn, argn;
|
||||
|
||||
cif = closure->cif;
|
||||
avalue = alloca(cif->nargs * sizeof(void *));
|
||||
|
||||
argn = 0;
|
||||
|
||||
/* Copy the caller's structure return address to that the closure
|
||||
returns the data directly to the caller. */
|
||||
if (cif->flags == FFI_TYPE_STRUCT)
|
||||
{
|
||||
rvalue = (void *) argp[0];
|
||||
argn = 1;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
avn = cif->nargs;
|
||||
arg_types = cif->arg_types;
|
||||
|
||||
/* Grab the addresses of the arguments from the stack frame. */
|
||||
while (i < avn)
|
||||
{
|
||||
switch (arg_types[i]->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_POINTER:
|
||||
case FFI_TYPE_STRUCT:
|
||||
avalue[i] = &argp[argn];
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (argn < 6)
|
||||
{
|
||||
/* Floats coming from registers need conversion from double
|
||||
back to float format. */
|
||||
*(float *)&argp[argn - 6] = *(double *)&argp[argn - 6];
|
||||
avalue[i] = &argp[argn - 6];
|
||||
}
|
||||
else
|
||||
avalue[i] = &argp[argn];
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
avalue[i] = &argp[argn - (argn < 6 ? 6 : 0)];
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
|
||||
argn += ALIGN(arg_types[i]->size, SIZEOF_ARG) / SIZEOF_ARG;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
/* Tell ffi_closure_osf how to perform return type promotions. */
|
||||
return cif->rtype->type;
|
||||
}
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
Alpha/OSF Foreign Function Interface
|
||||
|
||||
$Id: osf.S,v 1.1 1998/11/29 16:48:16 green Exp $
|
||||
|
||||
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
|
||||
@@ -28,91 +26,252 @@
|
||||
#define LIBFFI_ASM
|
||||
#include <ffi.h>
|
||||
|
||||
#define callback $16
|
||||
#define ecifp $17
|
||||
#define bytes $18
|
||||
#define flags $19
|
||||
#define raddr $20
|
||||
#define fn $21
|
||||
|
||||
#define flags_ofs 16
|
||||
#define raddr_ofs 24
|
||||
#define fn_ofs 32
|
||||
|
||||
#define SIZEOF_FRAME (6*8)
|
||||
|
||||
.arch ev6
|
||||
.text
|
||||
.align 4
|
||||
|
||||
/* ffi_call_osf (void *args, unsigned long bytes, unsigned flags,
|
||||
void *raddr, void (*fnaddr)());
|
||||
|
||||
Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
|
||||
for this function. This has been allocated by ffi_call. We also
|
||||
deallocate some of the stack that has been alloca'd. */
|
||||
|
||||
.align 3
|
||||
.globl ffi_call_osf
|
||||
.ent ffi_call_osf
|
||||
|
||||
ffi_call_osf:
|
||||
lda $30, -SIZEOF_FRAME($30)
|
||||
stq $26, 0($30)
|
||||
stq $15, 8($30)
|
||||
stq flags, flags_ofs($30)
|
||||
stq raddr, raddr_ofs($30)
|
||||
stq fn, fn_ofs($30)
|
||||
mov $30, $15
|
||||
.frame $15, SIZEOF_FRAME, $26, 0
|
||||
.mask 0x4008000, -SIZEOF_FRAME
|
||||
.frame $15, 32, $26, 0
|
||||
.mask 0x4008000, -32
|
||||
addq $16,$17,$1
|
||||
mov $16, $30
|
||||
stq $26, 0($1)
|
||||
stq $15, 8($1)
|
||||
stq $18, 16($1)
|
||||
mov $1, $15
|
||||
.prologue 0
|
||||
|
||||
mov callback, $27 # mov callback into place
|
||||
subq $30, bytes, $30 # allocate stack space
|
||||
|
||||
# Call ffi_prep_args; ecif, bytes and flags are already in place.
|
||||
mov $30, $16 # push stack arg
|
||||
jsr $26, ($27), 0
|
||||
stq $19, 24($1)
|
||||
mov $20, $27
|
||||
|
||||
# Load up all of the (potential) argument registers.
|
||||
ldq $16, 0($30)
|
||||
ldt $f16, 0($30)
|
||||
ldt $f17, 8($30)
|
||||
ldq $17, 8($30)
|
||||
ldt $f18, 16($30)
|
||||
ldq $18, 16($30)
|
||||
ldt $f19, 24($30)
|
||||
ldq $19, 24($30)
|
||||
ldt $f20, 32($30)
|
||||
ldq $20, 32($30)
|
||||
ldt $f21, 40($30)
|
||||
ldq $16, 48($30)
|
||||
ldq $17, 56($30)
|
||||
ldq $18, 64($30)
|
||||
ldq $19, 72($30)
|
||||
ldq $20, 80($30)
|
||||
ldq $21, 88($30)
|
||||
ldq $21, 40($30)
|
||||
|
||||
# Deallocate the register argument area.
|
||||
lda $30, 48($30)
|
||||
|
||||
# Get rid of the arg reg temp space and call the function.
|
||||
ldq $27, fn_ofs($15)
|
||||
lda $30, 12*8($30)
|
||||
jsr $26, ($27), 0
|
||||
ldgp $29, 0($26)
|
||||
|
||||
# If the return value pointer is NULL, assume no return value.
|
||||
ldq raddr, raddr_ofs($15)
|
||||
beq raddr, $noretval
|
||||
|
||||
ldq flags, flags_ofs($15)
|
||||
cmpeq flags, FFI_TYPE_INT, $1
|
||||
bne $1, $retint
|
||||
cmpeq flags, FFI_TYPE_FLOAT, $2
|
||||
bne $2, $retfloat
|
||||
cmpeq flags, FFI_TYPE_DOUBLE, $3
|
||||
bne $3, $retdouble
|
||||
br $retstruct
|
||||
|
||||
.align 3
|
||||
$retint:
|
||||
stq $0, 0(raddr)
|
||||
br $noretval
|
||||
$retfloat:
|
||||
sts $f0, 0(raddr)
|
||||
br $noretval
|
||||
$retdouble:
|
||||
stt $f0, 0(raddr)
|
||||
|
||||
$retstruct:
|
||||
$noretval:
|
||||
mov $15, $30
|
||||
ldq $19, 24($15)
|
||||
ldq $18, 16($15)
|
||||
ldq $26, 0($15)
|
||||
beq $19, $noretval
|
||||
|
||||
# Store the return value out in the proper type.
|
||||
cmpeq $18, FFI_TYPE_INT, $1
|
||||
bne $1, $retint
|
||||
cmpeq $18, FFI_TYPE_FLOAT, $2
|
||||
bne $2, $retfloat
|
||||
cmpeq $18, FFI_TYPE_DOUBLE, $3
|
||||
bne $3, $retdouble
|
||||
|
||||
$noretval:
|
||||
ldq $15, 8($15)
|
||||
ret
|
||||
|
||||
$retint:
|
||||
stq $0, 0($19)
|
||||
nop
|
||||
ldq $15, 8($15)
|
||||
ret
|
||||
|
||||
$retfloat:
|
||||
sts $f0, 0($19)
|
||||
nop
|
||||
ldq $15, 8($15)
|
||||
ret
|
||||
|
||||
$retdouble:
|
||||
stt $f0, 0($19)
|
||||
nop
|
||||
ldq $15, 8($15)
|
||||
lda $30, SIZEOF_FRAME($30)
|
||||
ret
|
||||
|
||||
.end ffi_call_osf
|
||||
|
||||
/* ffi_closure_osf(...)
|
||||
|
||||
Receives the closure argument in $1. */
|
||||
|
||||
.align 3
|
||||
.globl ffi_closure_osf
|
||||
.ent ffi_closure_osf
|
||||
ffi_closure_osf:
|
||||
.frame $30, 16*8, $26, 0
|
||||
.mask 0x4000000, -16*8
|
||||
ldgp $29, 0($27)
|
||||
subq $30, 16*8, $30
|
||||
stq $26, 0($30)
|
||||
.prologue 1
|
||||
|
||||
# Store all of the potential argument registers in va_list format.
|
||||
stt $f16, 4*8($30)
|
||||
stt $f17, 5*8($30)
|
||||
stt $f18, 6*8($30)
|
||||
stt $f19, 7*8($30)
|
||||
stt $f20, 8*8($30)
|
||||
stt $f21, 9*8($30)
|
||||
stq $16, 10*8($30)
|
||||
stq $17, 11*8($30)
|
||||
stq $18, 12*8($30)
|
||||
stq $19, 13*8($30)
|
||||
stq $20, 14*8($30)
|
||||
stq $21, 15*8($30)
|
||||
|
||||
# Call ffi_closure_osf_inner to do the bulk of the work.
|
||||
mov $1, $16
|
||||
lda $17, 2*8($30)
|
||||
lda $18, 10*8($30)
|
||||
jsr $26, ffi_closure_osf_inner
|
||||
ldgp $29, 0($26)
|
||||
ldq $26, 0($30)
|
||||
|
||||
# Load up the return value in the proper type.
|
||||
lda $1, $load_table
|
||||
s4addq $0, $1, $1
|
||||
ldl $1, 0($1)
|
||||
addq $1, $29, $1
|
||||
jmp $31, ($1), $load_32
|
||||
|
||||
.align 4
|
||||
$load_none:
|
||||
addq $30, 16*8, $30
|
||||
ret
|
||||
|
||||
.align 4
|
||||
$load_float:
|
||||
lds $f0, 16($30)
|
||||
nop
|
||||
addq $30, 16*8, $30
|
||||
ret
|
||||
|
||||
.align 4
|
||||
$load_double:
|
||||
ldt $f0, 16($30)
|
||||
nop
|
||||
addq $30, 16*8, $30
|
||||
ret
|
||||
|
||||
.align 4
|
||||
$load_u8:
|
||||
#ifdef __alpha_bwx__
|
||||
ldbu $0, 16($30)
|
||||
nop
|
||||
#else
|
||||
ldq $0, 16($30)
|
||||
and $0, 255, $0
|
||||
#endif
|
||||
addq $30, 16*8, $30
|
||||
ret
|
||||
|
||||
.align 4
|
||||
$load_s8:
|
||||
#ifdef __alpha_bwx__
|
||||
ldbu $0, 16($30)
|
||||
sextb $0, $0
|
||||
#else
|
||||
ldq $0, 16($30)
|
||||
sll $0, 56, $0
|
||||
sra $0, 56, $0
|
||||
#endif
|
||||
addq $30, 16*8, $30
|
||||
ret
|
||||
|
||||
.align 4
|
||||
$load_u16:
|
||||
#ifdef __alpha_bwx__
|
||||
ldwu $0, 16($30)
|
||||
nop
|
||||
#else
|
||||
ldq $0, 16($30)
|
||||
zapnot $0, 3, $0
|
||||
#endif
|
||||
addq $30, 16*8, $30
|
||||
ret
|
||||
|
||||
.align 4
|
||||
$load_s16:
|
||||
#ifdef __alpha_bwx__
|
||||
ldwu $0, 16($30)
|
||||
sextw $0, $0
|
||||
#else
|
||||
ldq $0, 16($30)
|
||||
sll $0, 48, $0
|
||||
sra $0, 48, $0
|
||||
#endif
|
||||
addq $30, 16*8, $30
|
||||
ret
|
||||
|
||||
.align 4
|
||||
$load_32:
|
||||
ldl $0, 16($30)
|
||||
nop
|
||||
addq $30, 16*8, $30
|
||||
ret
|
||||
|
||||
.align 4
|
||||
$load_64:
|
||||
ldq $0, 16($30)
|
||||
nop
|
||||
addq $30, 16*8, $30
|
||||
ret
|
||||
|
||||
.end ffi_closure_osf
|
||||
|
||||
.section .rodata
|
||||
$load_table:
|
||||
.gprel32 $load_none # FFI_TYPE_VOID
|
||||
.gprel32 $load_32 # FFI_TYPE_INT
|
||||
.gprel32 $load_float # FFI_TYPE_FLOAT
|
||||
.gprel32 $load_double # FFI_TYPE_DOUBLE
|
||||
.gprel32 $load_double # FFI_TYPE_LONGDOUBLE
|
||||
.gprel32 $load_u8 # FFI_TYPE_UINT8
|
||||
.gprel32 $load_s8 # FFI_TYPE_SINT8
|
||||
.gprel32 $load_u16 # FFI_TYPE_UINT16
|
||||
.gprel32 $load_s16 # FFI_TYPE_SINT16
|
||||
.gprel32 $load_32 # FFI_TYPE_UINT32
|
||||
.gprel32 $load_32 # FFI_TYPE_SINT32
|
||||
.gprel32 $load_64 # FFI_TYPE_UINT64
|
||||
.gprel32 $load_64 # FFI_TYPE_SINT64
|
||||
.gprel32 $load_none # FFI_TYPE_STRUCT
|
||||
.gprel32 $load_64 # FFI_TYPE_POINTER
|
||||
|
||||
/* Assert that the table above is in sync with ffi.h. */
|
||||
|
||||
#if FFI_TYPE_FLOAT != 2 \
|
||||
|| FFI_TYPE_DOUBLE != 3 \
|
||||
|| FFI_TYPE_UINT8 != 5 \
|
||||
|| FFI_TYPE_SINT8 != 6 \
|
||||
|| FFI_TYPE_UINT16 != 7 \
|
||||
|| FFI_TYPE_SINT16 != 8 \
|
||||
|| FFI_TYPE_UINT32 != 9 \
|
||||
|| FFI_TYPE_SINT32 != 10 \
|
||||
|| FFI_TYPE_UINT64 != 11 \
|
||||
|| FFI_TYPE_SINT64 != 12 \
|
||||
|| FFI_TYPE_STRUCT != 13 \
|
||||
|| FFI_TYPE_POINTER != 14 \
|
||||
|| FFI_TYPE_LAST != 14
|
||||
#error "osf.S out of sync with ffi.h"
|
||||
#endif
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
ARM Foreign Function Interface
|
||||
|
||||
$Id: ffi.c,v 1.1 1998/11/29 16:48:16 green Exp $
|
||||
|
||||
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
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
ARM Foreign Function Interface
|
||||
|
||||
$Id: sysv.S,v 1.1 1998/11/29 16:48:16 green Exp $
|
||||
|
||||
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
|
||||
@@ -97,19 +95,13 @@ ENTRY(ffi_call_SYSV)
|
||||
beq epilogue
|
||||
|
||||
# return FLOAT
|
||||
cmp a4, #FFI_TYPE_FLOAT
|
||||
bne retdouble
|
||||
stfs f0, [a3]
|
||||
b epilogue
|
||||
cmp a4, #FFI_TYPE_FLOAT
|
||||
stfeqs f0, [a3]
|
||||
beq epilogue
|
||||
|
||||
# return DOUBLE or LONGDOUBLE
|
||||
retdouble:
|
||||
cmp a4, #FFI_TYPE_DOUBLE
|
||||
bne epilogue
|
||||
|
||||
stfs f0, [a3, #0]
|
||||
stfs f1, [a3, #4]
|
||||
b epilogue
|
||||
cmp a4, #FFI_TYPE_DOUBLE
|
||||
stfeqd f0, [a3]
|
||||
|
||||
epilogue:
|
||||
ldmfd sp!, {a1-a4, fp, pc}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
debug.c - Copyright (c) 1996 Cygnus Solutions
|
||||
|
||||
$Id: debug.c,v 1.1 1998/11/29 16:48:16 green Exp $
|
||||
debug.c - Copyright (c) 1996 Red Hat, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
@@ -17,7 +15,7 @@
|
||||
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 CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
IN NO EVENT SHALL RED HAT 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.
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffitest.c - Copyright (c) 1996, 1997, 1998 Cygnus Solutions
|
||||
|
||||
$Id: ffitest.c,v 1.1 1998/11/29 16:48:16 green Exp $
|
||||
|
||||
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
|
||||
@@ -17,7 +15,7 @@
|
||||
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 CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
IN NO EVENT SHALL RED HAT 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.
|
||||
@@ -196,6 +194,16 @@ static test_structure_5 struct5(test_structure_5 ts1, test_structure_5 ts2)
|
||||
return ts1;
|
||||
}
|
||||
|
||||
/* Take an int and a float argument, together with int userdata, and */
|
||||
/* return the sum. */
|
||||
static void closure_test_fn(ffi_cif* cif,void* resp,void** args, void* userdata)
|
||||
{
|
||||
*(int*)resp =
|
||||
*(int *)args[0] + (int)(*(float *)args[1]) + (int)(long)userdata;
|
||||
}
|
||||
|
||||
typedef int (*closure_test_type)(int, float);
|
||||
|
||||
int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
|
||||
{
|
||||
ffi_cif cif;
|
||||
@@ -214,7 +222,7 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
|
||||
signed int si1;
|
||||
signed int si2;
|
||||
|
||||
#if defined(ALPHA) || (defined(MIPS) && (_MIPS_SIM == _ABIN32))
|
||||
#if defined(ALPHA) || defined(IA64) || defined(SPARC64) || (defined(MIPS) && (_MIPS_SIM == _ABIN32))
|
||||
long long rint;
|
||||
#else
|
||||
int rint;
|
||||
@@ -285,7 +293,7 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
|
||||
|
||||
/* return value tests */
|
||||
{
|
||||
#if defined(MIPS) || defined(SPARC) /* || defined(ARM) */
|
||||
#if defined(MIPS) /* || defined(ARM) */
|
||||
puts ("long long tests not run. This is a known bug on this architecture.");
|
||||
#else
|
||||
args[0] = &ffi_type_sint64;
|
||||
@@ -533,6 +541,8 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
|
||||
printf("%lu promotion tests run\n", ul);
|
||||
}
|
||||
|
||||
#ifndef X86_WIN32 /* Structures dont work on Win32 */
|
||||
|
||||
/* struct tests */
|
||||
{
|
||||
test_structure_1 ts1_arg;
|
||||
@@ -691,6 +701,31 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
|
||||
free (ts5_result);
|
||||
}
|
||||
|
||||
#else
|
||||
printf("Structure passing doesn't work on Win32.\n");
|
||||
#endif /* X86_WIN32 */
|
||||
|
||||
# if FFI_CLOSURES
|
||||
/* A simple closure test */
|
||||
{
|
||||
ffi_closure cl;
|
||||
ffi_type * cl_arg_types[3];
|
||||
|
||||
cl_arg_types[0] = &ffi_type_sint;
|
||||
cl_arg_types[1] = &ffi_type_float;
|
||||
cl_arg_types[2] = NULL;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
|
||||
&ffi_type_sint, cl_arg_types) == FFI_OK);
|
||||
|
||||
CHECK(ffi_prep_closure(&cl, &cif, closure_test_fn,
|
||||
(void *) 3 /* userdata */)
|
||||
== FFI_OK);
|
||||
CHECK((*((closure_test_type)(&cl)))(1, 2.0) == 6);
|
||||
}
|
||||
# endif
|
||||
|
||||
/* If we arrived here, all is good */
|
||||
(void) puts("\nLooks good. No surprises.\n");
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
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 CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
IN NO EVENT SHALL RED HAT 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.
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
MIPS Foreign Function Interface
|
||||
|
||||
$Id: ffi.c,v 1.1 1998/11/29 16:48:16 green Exp $
|
||||
|
||||
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
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
MIPS Foreign Function Interface
|
||||
|
||||
$Id: n32.S,v 1.1 1998/11/29 16:48:16 green Exp $
|
||||
|
||||
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
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
MIPS Foreign Function Interface
|
||||
|
||||
$Id: o32.S,v 1.1 1998/11/29 16:48:16 green Exp $
|
||||
|
||||
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
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
PowerPC Foreign Function Interface
|
||||
|
||||
$Id: ffi.c,v 1.1 1998/11/29 16:48:16 green Exp $
|
||||
$Id: ffi.c,v 1.2 2001/04/09 00:58:37 green Exp $
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
@@ -29,6 +29,9 @@
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
extern void ffi_closure_SYSV(void);
|
||||
|
||||
enum {
|
||||
/* The assembly depends on these exact flags. */
|
||||
@@ -172,6 +175,18 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* whoops: abi states only certain register pairs
|
||||
* can be used for passing long long int
|
||||
* specifically (r3,r4), (r5,r6), (r7,r8),
|
||||
* (r9,r10) and if next arg is long long but
|
||||
* not correct starting register of pair then skip
|
||||
* until the proper starting register
|
||||
*/
|
||||
if (intarg_count%2 != 0)
|
||||
{
|
||||
intarg_count ++;
|
||||
gpr_base++;
|
||||
}
|
||||
*(long long *)gpr_base = *(long long *)*p_argv;
|
||||
gpr_base += 2;
|
||||
}
|
||||
@@ -421,3 +436,245 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void flush_icache(char *, int);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data)
|
||||
{
|
||||
unsigned int *tramp;
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
|
||||
|
||||
tramp = (unsigned int *) &closure->tramp[0];
|
||||
tramp[0] = 0x7c0802a6; /* mflr r0 */
|
||||
tramp[1] = 0x4800000d; /* bl 10 <trampoline_initial+0x10> */
|
||||
tramp[4] = 0x7d6802a6; /* mflr r11 */
|
||||
tramp[5] = 0x7c0803a6; /* mtlr r0 */
|
||||
tramp[6] = 0x800b0000; /* lwz r0,0(r11) */
|
||||
tramp[7] = 0x816b0004; /* lwz r11,4(r11) */
|
||||
tramp[8] = 0x7c0903a6; /* mtctr r0 */
|
||||
tramp[9] = 0x4e800420; /* bctr */
|
||||
*(void **) &tramp[2] = (void *)ffi_closure_SYSV; /* function */
|
||||
*(void **) &tramp[3] = (void *)closure; /* context */
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
/* Flush the icache. */
|
||||
flush_icache(&closure->tramp[0],FFI_TRAMPOLINE_SIZE);
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
|
||||
#define MIN_CACHE_LINE_SIZE 8
|
||||
|
||||
static void flush_icache(char * addr1, int size)
|
||||
{
|
||||
int i;
|
||||
char * addr;
|
||||
for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE) {
|
||||
addr = addr1 + i;
|
||||
__asm__ volatile ("icbi 0,%0;" "dcbf 0,%0;" : : "r"(addr) : "memory");
|
||||
}
|
||||
addr = addr1 + size - 1;
|
||||
__asm__ volatile ("icbi 0,%0;" "dcbf 0,%0;" "sync;" "isync;" : : "r"(addr) : "memory");
|
||||
}
|
||||
|
||||
|
||||
int ffi_closure_helper_SYSV (ffi_closure*, void*, unsigned long*,
|
||||
unsigned long*, unsigned long*);
|
||||
|
||||
/* Basically the trampoline invokes ffi_closure_SYSV, and on
|
||||
* entry, r11 holds the address of the closure.
|
||||
* After storing the registers that could possibly contain
|
||||
* parameters to be passed into the stack frame and setting
|
||||
* up space for a return value, ffi_closure_SYSV invokes the
|
||||
* following helper function to do most of the work
|
||||
*/
|
||||
|
||||
int
|
||||
ffi_closure_helper_SYSV (ffi_closure* closure, void * rvalue,
|
||||
unsigned long * pgr, unsigned long * pfr,
|
||||
unsigned long * pst)
|
||||
{
|
||||
/* rvalue is the pointer to space for return value in closure assembly */
|
||||
/* pgr is the pointer to where r3-r10 are stored in ffi_closure_SYSV */
|
||||
/* pfr is the pointer to where f1-f8 are stored in ffi_closure_SYSV */
|
||||
/* pst is the pointer to outgoing parameter stack in original caller */
|
||||
|
||||
void ** avalue;
|
||||
ffi_type ** arg_types;
|
||||
long i, avn;
|
||||
long nf; /* number of floating registers already used */
|
||||
long ng; /* number of general registers already used */
|
||||
ffi_cif * cif;
|
||||
double temp;
|
||||
|
||||
cif = closure->cif;
|
||||
avalue = alloca(cif->nargs * sizeof(void *));
|
||||
|
||||
nf = 0;
|
||||
ng = 0;
|
||||
|
||||
/* Copy the caller's structure return value address so that the closure
|
||||
returns the data directly to the caller. */
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
rvalue = *pgr;
|
||||
ng++;
|
||||
pgr++;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
avn = cif->nargs;
|
||||
arg_types = cif->arg_types;
|
||||
|
||||
/* Grab the addresses of the arguments from the stack frame. */
|
||||
while (i < avn)
|
||||
{
|
||||
switch (arg_types[i]->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT8:
|
||||
/* there are 8 gpr registers used to pass values */
|
||||
if (ng < 8) {
|
||||
avalue[i] = (((char *)pgr)+3);
|
||||
ng++;
|
||||
pgr++;
|
||||
} else {
|
||||
avalue[i] = (((char *)pst)+3);
|
||||
pst++;
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
/* there are 8 gpr registers used to pass values */
|
||||
if (ng < 8) {
|
||||
avalue[i] = (((char *)pgr)+2);
|
||||
ng++;
|
||||
pgr++;
|
||||
} else {
|
||||
avalue[i] = (((char *)pst)+2);
|
||||
pst++;
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_POINTER:
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* there are 8 gpr registers used to pass values */
|
||||
if (ng < 8) {
|
||||
avalue[i] = pgr;
|
||||
ng++;
|
||||
pgr++;
|
||||
} else {
|
||||
avalue[i] = pst;
|
||||
pst++;
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
/* passing long long ints are complex, they must
|
||||
* be passed in suitable register pairs such as
|
||||
* (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
|
||||
* and if the entire pair aren't available then the outgoing
|
||||
* parameter stack is used for both but an alignment of 8
|
||||
* must will be kept. So we must either look in pgr
|
||||
* or pst to find the correct address for this type
|
||||
* of parameter.
|
||||
*/
|
||||
if (ng < 7) {
|
||||
if (ng & 0x01) {
|
||||
/* skip r4, r6, r8 as starting points */
|
||||
ng++;
|
||||
pgr++;
|
||||
}
|
||||
avalue[i] = pgr;
|
||||
ng+=2;
|
||||
pgr+=2;
|
||||
} else {
|
||||
if (((long)pst) & 4) pst++;
|
||||
avalue[i] = pst;
|
||||
pst+=2;
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
/* unfortunately float values are stored as doubles
|
||||
* in the ffi_closure_SYSV code (since we don't check
|
||||
* the type in that routine). This is also true
|
||||
* of floats passed on the outgoing parameter stack.
|
||||
* Also, on the outgoing stack all values are aligned
|
||||
* to 8
|
||||
*
|
||||
* Don't you just love the simplicity of this ABI!
|
||||
*/
|
||||
|
||||
/* there are 8 64bit floating point registers */
|
||||
|
||||
if (nf < 8) {
|
||||
temp = *(double*)pfr;
|
||||
*(float*)pfr = (float)temp;
|
||||
avalue[i] = pfr;
|
||||
nf++;
|
||||
pfr+=2;
|
||||
} else {
|
||||
/* FIXME? here we are really changing the values
|
||||
* stored in the original calling routines outgoing
|
||||
* parameter stack. This is probably a really
|
||||
* naughty thing to do but...
|
||||
*/
|
||||
if (((long)pst) & 4) pst++;
|
||||
temp = *(double*)pst;
|
||||
*(float*)pst = (float)temp;
|
||||
avalue[i] = pst;
|
||||
nf++;
|
||||
pst+=2;
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
/* On the outgoing stack all values are aligned to 8 */
|
||||
/* there are 8 64bit floating point registers */
|
||||
|
||||
if (nf < 8) {
|
||||
avalue[i] = pfr;
|
||||
nf++;
|
||||
pfr+=2;
|
||||
} else {
|
||||
if (((long)pst) & 4) pst++;
|
||||
avalue[i] = pst;
|
||||
nf++;
|
||||
pst+=2;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
/* Tell ffi_closure_osf how to perform return type promotions. */
|
||||
return cif->rtype->type;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
148
libffi/src/powerpc/ppc_closure.S
Normal file
148
libffi/src/powerpc/ppc_closure.S
Normal file
@@ -0,0 +1,148 @@
|
||||
#define LIBFFI_ASM
|
||||
#include <powerpc/asm.h>
|
||||
|
||||
.globl ffi_closure_helper_SYSV
|
||||
|
||||
ENTRY(ffi_closure_SYSV)
|
||||
stwu %r1,-144(%r1)
|
||||
mflr %r0
|
||||
stw %r31,140(%r1)
|
||||
stw %r0,148(%r1)
|
||||
|
||||
# we want to build up an areas for the parameters passed
|
||||
# in registers (both floating point and integer)
|
||||
|
||||
# so first save gpr 3 to gpr 10 (aligned to 4)
|
||||
stw %r3, 16(%r1)
|
||||
stw %r4, 20(%r1)
|
||||
stw %r5, 24(%r1)
|
||||
stw %r6, 28(%r1)
|
||||
stw %r7, 32(%r1)
|
||||
stw %r8, 36(%r1)
|
||||
stw %r9, 40(%r1)
|
||||
stw %r10,44(%r1)
|
||||
|
||||
# next save fpr 1 to fpr 8 (aligned to 8)
|
||||
stfd %f1, 48(%r1)
|
||||
stfd %f2, 56(%r1)
|
||||
stfd %f3, 64(%r1)
|
||||
stfd %f4, 72(%r1)
|
||||
stfd %f5, 80(%r1)
|
||||
stfd %f6, 88(%r1)
|
||||
stfd %f7, 96(%r1)
|
||||
stfd %f8, 104(%r1)
|
||||
|
||||
# set up registers for the routine that actually does the work
|
||||
# get the context pointer from the trampoline
|
||||
mr %r3,%r11
|
||||
|
||||
# now load up the pointer to the result storage
|
||||
addi %r4,%r1,112
|
||||
|
||||
# now load up the pointer to the saved gpr registers
|
||||
addi %r5,%r1,16
|
||||
|
||||
# now load up the pointer to the saved fpr registers */
|
||||
addi %r6,%r1,48
|
||||
|
||||
# now load up the pointer to the outgoing parameter
|
||||
# stack in the previous frame
|
||||
# i.e. the previous frame pointer + 8
|
||||
addi %r7,%r1,152
|
||||
|
||||
# make the call
|
||||
bl JUMPTARGET(ffi_closure_helper_SYSV)
|
||||
|
||||
# now r3 contains the return type
|
||||
# so use it to look up in a table
|
||||
# so we know how to deal with each type
|
||||
|
||||
# look up the proper starting point in table
|
||||
# by using return type as offset
|
||||
addi %r5,%r1,112 # get pointer to results area
|
||||
addis %r4,0,.L60@ha # get address of jump table
|
||||
addi %r4,%r4,.L60@l
|
||||
slwi %r3,%r3,2 # now multiply return type by 4
|
||||
lwzx %r3,%r4,%r3 # get the contents of that table value
|
||||
add %r3,%r3,%r4 # add contents of table to table address
|
||||
mtctr %r3
|
||||
bctr # jump to it
|
||||
.align 2
|
||||
.L60:
|
||||
.long .L44-.L60 # FFI_TYPE_VOID
|
||||
.long .L50-.L60 # FFI_TYPE_INT
|
||||
.long .L47-.L60 # FFI_TYPE_FLOAT
|
||||
.long .L46-.L60 # FFI_TYPE_DOUBLE
|
||||
.long .L46-.L60 # FFI_TYPE_LONGDOUBLE
|
||||
.long .L56-.L60 # FFI_TYPE_UINT8
|
||||
.long .L55-.L60 # FFI_TYPE_SINT8
|
||||
.long .L58-.L60 # FFI_TYPE_UINT16
|
||||
.long .L57-.L60 # FFI_TYPE_SINT16
|
||||
.long .L50-.L60 # FFI_TYPE_UINT32
|
||||
.long .L50-.L60 # FFI_TYPE_SINT32
|
||||
.long .L48-.L60 # FFI_TYPE_UINT64
|
||||
.long .L48-.L60 # FFI_TYPE_SINT64
|
||||
.long .L44-.L60 # FFI_TYPE_STRUCT
|
||||
.long .L50-.L60 # FFI_TYPE_POINTER
|
||||
|
||||
|
||||
# case double
|
||||
.L46:
|
||||
lfd %f1,0(%r5)
|
||||
b .L44
|
||||
|
||||
# case float
|
||||
.L47:
|
||||
lfs %f1,0(%r5)
|
||||
b .L44
|
||||
|
||||
# case long long
|
||||
.L48:
|
||||
lwz %r3,0(%r5)
|
||||
lwz %r4,4(%r5)
|
||||
b .L44
|
||||
|
||||
# case default / int32 / pointer
|
||||
.L50:
|
||||
lwz %r3,0(%r5)
|
||||
b .L44
|
||||
|
||||
# case signed int8
|
||||
.L55:
|
||||
addi %r5,%r5,3
|
||||
lbz %r3,0(%r5)
|
||||
extsb %r3,%r3
|
||||
b .L44
|
||||
|
||||
# case unsigned int8
|
||||
.L56:
|
||||
addi %r5,%r5,3
|
||||
lbz %r3,0(%r5)
|
||||
b .L44
|
||||
|
||||
# case signed int16
|
||||
.L57:
|
||||
addi %r5,%r5,2
|
||||
lhz %r3,0(%r5)
|
||||
extsh %r3,%r3
|
||||
b .L44
|
||||
|
||||
#case unsigned int16
|
||||
.L58:
|
||||
addi %r5,%r5,2
|
||||
lhz %r3,0(%r5)
|
||||
|
||||
# case void / done
|
||||
.L44:
|
||||
|
||||
lwz %r11,0(%r1)
|
||||
lwz %r0,4(%r11)
|
||||
mtlr %r0
|
||||
lwz %r31,-4(%r11)
|
||||
mr %r1,%r11
|
||||
blr
|
||||
END(ffi_closure_SYSV)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
prep_cif.c - Copyright (c) 1996, 1998 Cygnus Solutions
|
||||
|
||||
$Id: prep_cif.c,v 1.1 1998/11/29 16:48:16 green Exp $
|
||||
|
||||
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
|
||||
@@ -17,7 +15,7 @@
|
||||
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 CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
IN NO EVENT SHALL RED HAT 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.
|
||||
@@ -107,7 +105,11 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
|
||||
|
||||
#ifndef M68K
|
||||
/* Make space for the return structure pointer */
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT
|
||||
#ifdef SPARC
|
||||
&& (cif->abi != FFI_V9 || cif->rtype->size > 32)
|
||||
#endif
|
||||
)
|
||||
bytes = STACK_ARG_SIZE(sizeof(void*));
|
||||
#endif
|
||||
|
||||
@@ -121,8 +123,10 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
#ifdef SPARC
|
||||
if ((*ptr)->type == FFI_TYPE_STRUCT
|
||||
|| (*ptr)->type == FFI_TYPE_LONGDOUBLE)
|
||||
if (((*ptr)->type == FFI_TYPE_STRUCT
|
||||
&& ((*ptr)->size > 16 || cif->abi != FFI_V9))
|
||||
|| ((*ptr)->type == FFI_TYPE_LONGDOUBLE
|
||||
&& cif->abi != FFI_V9))
|
||||
bytes += sizeof(void*);
|
||||
else
|
||||
#endif
|
||||
@@ -140,4 +144,3 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
|
||||
/* Perform machine dependent cif processing */
|
||||
return ffi_prep_cif_machdep(cif);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
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 CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
IN NO EVENT SHALL RED HAT 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.
|
||||
@@ -202,13 +202,13 @@ void ffi_raw_call (/*@dependent@*/ ffi_cif *cif,
|
||||
#if FFI_CLOSURES /* base system provides closures */
|
||||
|
||||
static void
|
||||
ffi_translate_args (ffi_cif *cif, void *ravlue,
|
||||
ffi_translate_args (ffi_cif *cif, void *rvalue,
|
||||
void **avalue, void *user_data)
|
||||
{
|
||||
ffi_raw *raw = (ffi_raw*)alloca (ffi_raw_size (cif));
|
||||
ffi_ptrarray_to_raw (cif, avalue, raw);
|
||||
|
||||
ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
|
||||
|
||||
ffi_ptrarray_to_raw (cif, avalue, raw);
|
||||
(*cl->fun) (cif, rvalue, raw, cl->user_data);
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@ ffi_prep_raw_closure (ffi_raw_closure* cl,
|
||||
|
||||
status = ffi_prep_closure ((ffi_closure*) cl,
|
||||
cif,
|
||||
&ffi_closure_translate,
|
||||
&ffi_translate_args,
|
||||
(void*)cl);
|
||||
if (status == FFI_OK)
|
||||
{
|
||||
|
||||
589
libffi/src/s390/ffi.c
Normal file
589
libffi/src/s390/ffi.c
Normal file
@@ -0,0 +1,589 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2000 Software AG
|
||||
|
||||
S390 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 AUTHOR 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.
|
||||
----------------------------------------------------------------------- */
|
||||
/*====================================================================*/
|
||||
/* Includes */
|
||||
/* -------- */
|
||||
/*====================================================================*/
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*====================== End of Includes =============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* Defines */
|
||||
/* ------- */
|
||||
/*====================================================================*/
|
||||
|
||||
#define MAX_GPRARGS 5 /* Max. no. of GPR available */
|
||||
#define MAX_FPRARGS 2 /* Max. no. of FPR available */
|
||||
|
||||
#define STR_GPR 1 /* Structure will fit in 1 or 2 GPR */
|
||||
#define STR_FPR 2 /* Structure will fit in a FPR */
|
||||
#define STR_STACK 3 /* Structure needs to go on stack */
|
||||
|
||||
/*===================== End of Defines ===============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* Types */
|
||||
/* ----- */
|
||||
/*====================================================================*/
|
||||
|
||||
typedef struct stackLayout
|
||||
{
|
||||
int *backChain;
|
||||
int *endOfStack;
|
||||
int glue[2];
|
||||
int scratch[2];
|
||||
int gprArgs[MAX_GPRARGS];
|
||||
int notUsed;
|
||||
union
|
||||
{
|
||||
float f;
|
||||
double d;
|
||||
} fprArgs[MAX_FPRARGS];
|
||||
int unUsed[8];
|
||||
int outArgs[100];
|
||||
} stackLayout;
|
||||
|
||||
/*======================== End of Types ==============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* Prototypes */
|
||||
/* ---------- */
|
||||
/*====================================================================*/
|
||||
|
||||
void ffi_prep_args(stackLayout *, extended_cif *);
|
||||
static int ffi_check_struct(ffi_type *, unsigned int *);
|
||||
static void ffi_insert_int(int, stackLayout *, int *, int *);
|
||||
static void ffi_insert_int64(long long, stackLayout *, int *, int *);
|
||||
static void ffi_insert_double(double, stackLayout *, int *, int *);
|
||||
|
||||
/*====================== End of Prototypes ===========================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* Externals */
|
||||
/* --------- */
|
||||
/*====================================================================*/
|
||||
|
||||
extern void ffi_call_SYSV(void (*)(stackLayout *, extended_cif *),
|
||||
extended_cif *,
|
||||
unsigned, unsigned,
|
||||
unsigned *,
|
||||
void (*fn)());
|
||||
|
||||
/*====================== End of Externals ============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_check_struct. */
|
||||
/* */
|
||||
/* Function - Determine if a structure can be passed within a */
|
||||
/* general or floating point register. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
int
|
||||
ffi_check_struct(ffi_type *arg, unsigned int *strFlags)
|
||||
{
|
||||
ffi_type *element;
|
||||
int i_Element;
|
||||
|
||||
for (i_Element = 0; arg->elements[i_Element]; i_Element++) {
|
||||
element = arg->elements[i_Element];
|
||||
switch (element->type) {
|
||||
case FFI_TYPE_DOUBLE :
|
||||
*strFlags |= STR_FPR;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT :
|
||||
*strFlags |= ffi_check_struct(element, strFlags);
|
||||
break;
|
||||
|
||||
default :
|
||||
*strFlags |= STR_GPR;
|
||||
}
|
||||
}
|
||||
return (*strFlags);
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_insert_int. */
|
||||
/* */
|
||||
/* Function - Insert an integer parameter in a register if there are */
|
||||
/* spares else on the stack. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
void
|
||||
ffi_insert_int(int gprValue, stackLayout *stack,
|
||||
int *intArgC, int *outArgC)
|
||||
{
|
||||
if (*intArgC < MAX_GPRARGS) {
|
||||
stack->gprArgs[*intArgC] = gprValue;
|
||||
*intArgC += 1;
|
||||
}
|
||||
else {
|
||||
stack->outArgs[*outArgC++] = gprValue;
|
||||
*outArgC += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_insert_int64. */
|
||||
/* */
|
||||
/* Function - Insert a long long parameter in registers if there are */
|
||||
/* spares else on the stack. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
void
|
||||
ffi_insert_int64(long long llngValue, stackLayout *stack,
|
||||
int *intArgC, int *outArgC)
|
||||
{
|
||||
|
||||
if (*intArgC < (MAX_GPRARGS-1)) {
|
||||
memcpy(&stack->gprArgs[*intArgC],
|
||||
&llngValue, sizeof(long long));
|
||||
*intArgC += 2;
|
||||
}
|
||||
else {
|
||||
memcpy(&stack->outArgs[*outArgC],
|
||||
&llngValue, sizeof(long long));
|
||||
*outArgC += 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_insert_double. */
|
||||
/* */
|
||||
/* Function - Insert a double parameter in a FP register if there is */
|
||||
/* a spare else on the stack. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
void
|
||||
ffi_insert_double(double dblValue, stackLayout *stack,
|
||||
int *fprArgC, int *outArgC)
|
||||
{
|
||||
|
||||
if (*fprArgC < MAX_FPRARGS) {
|
||||
stack->fprArgs[*fprArgC].d = dblValue;
|
||||
*fprArgC += 1;
|
||||
}
|
||||
else {
|
||||
memcpy(&stack->outArgs[*outArgC],
|
||||
&dblValue,sizeof(double));
|
||||
*outArgC += 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_prep_args. */
|
||||
/* */
|
||||
/* Function - Prepare parameters for call to function. */
|
||||
/* */
|
||||
/* ffi_prep_args is called by the assembly routine once stack space */
|
||||
/* has been allocated for the function's arguments. */
|
||||
/* */
|
||||
/* The stack layout we want looks like this: */
|
||||
/* *------------------------------------------------------------* */
|
||||
/* | 0 | Back chain (a 0 here signifies end of back chain) | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 4 | EOS (end of stack, not used on Linux for S390) | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 8 | Glue used in other linkage formats | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 12 | Glue used in other linkage formats | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 16 | Scratch area | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 20 | Scratch area | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 24 | GPR parameter register 1 | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 28 | GPR parameter register 2 | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 32 | GPR parameter register 3 | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 36 | GPR parameter register 4 | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 40 | GPR parameter register 5 | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 44 | Unused | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 48 | FPR parameter register 1 | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 56 | FPR parameter register 2 | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 64 | Unused | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 96 | Outgoing args (length x) | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 96+x | Copy area for structures (length y) | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 96+x+y | Possible stack alignment | */
|
||||
/* *------------------------------------------------------------* */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
void
|
||||
ffi_prep_args(stackLayout *stack, extended_cif *ecif)
|
||||
{
|
||||
const unsigned bytes = ecif->cif->bytes;
|
||||
const unsigned flags = ecif->cif->flags;
|
||||
|
||||
/*----------------------------------------------------------*/
|
||||
/* Pointer to the copy area on stack for structures */
|
||||
/*----------------------------------------------------------*/
|
||||
char *copySpace = (char *) stack + bytes + sizeof(stackLayout);
|
||||
|
||||
/*----------------------------------------------------------*/
|
||||
/* Count of general and floating point register usage */
|
||||
/*----------------------------------------------------------*/
|
||||
int intArgC = 0,
|
||||
fprArgC = 0,
|
||||
outArgC = 0;
|
||||
|
||||
int i;
|
||||
ffi_type **ptr;
|
||||
void **p_argv;
|
||||
size_t structCopySize;
|
||||
unsigned gprValue, strFlags = 0;
|
||||
unsigned long long llngValue;
|
||||
double dblValue;
|
||||
|
||||
/* Now for the arguments. */
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* If we returning a structure then we set the first parameter register */
|
||||
/* to the address of where we are returning this structure */
|
||||
/*----------------------------------------------------------------------*/
|
||||
if (flags == FFI_TYPE_STRUCT)
|
||||
stack->gprArgs[intArgC++] = (int) ecif->rvalue;
|
||||
|
||||
for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
|
||||
i > 0;
|
||||
i--, ptr++, p_argv++)
|
||||
{
|
||||
switch ((*ptr)->type) {
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (fprArgC < MAX_FPRARGS)
|
||||
stack->fprArgs[fprArgC++].f = *(float *) *p_argv;
|
||||
else
|
||||
stack->outArgs[outArgC++] = *(int *) *p_argv;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
dblValue = *(double *) *p_argv;
|
||||
ffi_insert_double(dblValue, stack, &fprArgC, &outArgC);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
llngValue = *(unsigned long long *) *p_argv;
|
||||
ffi_insert_int64(llngValue, stack, &intArgC, &outArgC);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
gprValue = *(unsigned char *)*p_argv;
|
||||
ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT8:
|
||||
gprValue = *(signed char *)*p_argv;
|
||||
ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
gprValue = *(unsigned short *)*p_argv;
|
||||
ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
gprValue = *(signed short *)*p_argv;
|
||||
ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
/*--------------------------------------------------*/
|
||||
/* If structure > 8 bytes then it goes on the stack */
|
||||
/*--------------------------------------------------*/
|
||||
if (((*ptr)->size > 8) ||
|
||||
((*ptr)->size > 4 &&
|
||||
(*ptr)->size < 8))
|
||||
strFlags = STR_STACK;
|
||||
else
|
||||
strFlags = ffi_check_struct((ffi_type *) *ptr, &strFlags);
|
||||
|
||||
switch (strFlags) {
|
||||
/*-------------------------------------------*/
|
||||
/* Structure that will fit in one or two GPR */
|
||||
/*-------------------------------------------*/
|
||||
case STR_GPR :
|
||||
if ((*ptr)->size <= 4) {
|
||||
gprValue = *(unsigned int *) *p_argv;
|
||||
gprValue = gprValue >> ((4 - (*ptr)->size) * 8);
|
||||
ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
|
||||
}
|
||||
else {
|
||||
llngValue = *(unsigned long long *) *p_argv;
|
||||
ffi_insert_int64(llngValue, stack, &intArgC, &outArgC);
|
||||
}
|
||||
break;
|
||||
|
||||
/*-------------------------------------------*/
|
||||
/* Structure that will fit in one FPR */
|
||||
/*-------------------------------------------*/
|
||||
case STR_FPR :
|
||||
dblValue = *(double *) *p_argv;
|
||||
ffi_insert_double(dblValue, stack, &fprArgC, &outArgC);
|
||||
break;
|
||||
|
||||
/*-------------------------------------------*/
|
||||
/* Structure that must be copied to stack */
|
||||
/*-------------------------------------------*/
|
||||
default :
|
||||
structCopySize = (((*ptr)->size + 15) & ~0xF);
|
||||
copySpace -= structCopySize;
|
||||
memcpy(copySpace, (char *)*p_argv, (*ptr)->size);
|
||||
gprValue = (unsigned) copySpace;
|
||||
if (intArgC < MAX_GPRARGS)
|
||||
stack->gprArgs[intArgC++] = gprValue;
|
||||
else
|
||||
stack->outArgs[outArgC++] = gprValue;
|
||||
}
|
||||
break;
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
structCopySize = (((*ptr)->size + 15) & ~0xF);
|
||||
copySpace -= structCopySize;
|
||||
memcpy(copySpace, (char *)*p_argv, (*ptr)->size);
|
||||
gprValue = (unsigned) copySpace;
|
||||
if (intArgC < MAX_GPRARGS)
|
||||
stack->gprArgs[intArgC++] = gprValue;
|
||||
else
|
||||
stack->outArgs[outArgC++] = gprValue;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_POINTER:
|
||||
gprValue = *(unsigned *)*p_argv;
|
||||
if (intArgC < MAX_GPRARGS)
|
||||
stack->gprArgs[intArgC++] = gprValue;
|
||||
else
|
||||
stack->outArgs[outArgC++] = gprValue;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_prep_cif_machdep. */
|
||||
/* */
|
||||
/* Function - Perform machine dependent CIF processing. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
int i;
|
||||
ffi_type **ptr;
|
||||
unsigned bytes;
|
||||
int fpArgC = 0,
|
||||
intArgC = 0;
|
||||
unsigned flags = 0;
|
||||
unsigned structCopySize = 0;
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
/* Extra space required in stack for overflow parameters. */
|
||||
/*-----------------------------------------------------------------*/
|
||||
bytes = 0;
|
||||
|
||||
/*--------------------------------------------------------*/
|
||||
/* Return value handling. The rules are as follows: */
|
||||
/* - 32-bit (or less) integer values are returned in gpr2 */
|
||||
/* - Structures are returned as pointers in gpr2 */
|
||||
/* - 64-bit integer values are returned in gpr2 and 3 */
|
||||
/* - Single/double FP values are returned in fpr0 */
|
||||
/*--------------------------------------------------------*/
|
||||
flags = cif->rtype->type;
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* The first MAX_GPRARGS words of integer arguments, and the */
|
||||
/* first MAX_FPRARGS floating point arguments, go in registers; the rest */
|
||||
/* goes on the stack. Structures and long doubles (if not equivalent */
|
||||
/* to double) are passed as a pointer to a copy of the structure. */
|
||||
/* Stuff on the stack needs to keep proper alignment. */
|
||||
/*------------------------------------------------------------------------*/
|
||||
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
||||
{
|
||||
switch ((*ptr)->type)
|
||||
{
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
fpArgC++;
|
||||
if (fpArgC > MAX_FPRARGS && intArgC%2 != 0)
|
||||
intArgC++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
/*----------------------------------------------------*/
|
||||
/* 'long long' arguments are passed as two words, but */
|
||||
/* either both words must fit in registers or both go */
|
||||
/* on the stack. If they go on the stack, they must */
|
||||
/* be 8-byte-aligned. */
|
||||
/*----------------------------------------------------*/
|
||||
if ((intArgC == MAX_GPRARGS-1) ||
|
||||
(intArgC >= MAX_GPRARGS) &&
|
||||
(intArgC%2 != 0))
|
||||
intArgC++;
|
||||
intArgC += 2;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
#endif
|
||||
/*----------------------------------------------------*/
|
||||
/* We must allocate space for a copy of these to */
|
||||
/* enforce pass-by-value. Pad the space up to a */
|
||||
/* multiple of 16 bytes (the maximum alignment */
|
||||
/* required for anything under the SYSV ABI). */
|
||||
/*----------------------------------------------------*/
|
||||
structCopySize += ((*ptr)->size + 15) & ~0xF;
|
||||
/*----------------------------------------------------*/
|
||||
/* Fall through (allocate space for the pointer). */
|
||||
/*----------------------------------------------------*/
|
||||
|
||||
default:
|
||||
/*----------------------------------------------------*/
|
||||
/* Everything else is passed as a 4-byte word in a */
|
||||
/* GPR either the object itself or a pointer to it. */
|
||||
/*----------------------------------------------------*/
|
||||
intArgC++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
/* Stack space. */
|
||||
/*-----------------------------------------------------------------*/
|
||||
if (intArgC > MAX_GPRARGS)
|
||||
bytes += (intArgC - MAX_GPRARGS) * sizeof(int);
|
||||
if (fpArgC > MAX_FPRARGS)
|
||||
bytes += (fpArgC - MAX_FPRARGS) * sizeof(double);
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
/* The stack space allocated needs to be a multiple of 16 bytes. */
|
||||
/*-----------------------------------------------------------------*/
|
||||
bytes = (bytes + 15) & ~0xF;
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
/* Add in the space for the copied structures. */
|
||||
/*-----------------------------------------------------------------*/
|
||||
bytes += structCopySize;
|
||||
|
||||
cif->flags = flags;
|
||||
cif->bytes = bytes;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_call. */
|
||||
/* */
|
||||
/* Function - Call the FFI routine. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
void
|
||||
ffi_call(ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
void *rvalue,
|
||||
void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
/* 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))
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
ffi_call_SYSV(ffi_prep_args,
|
||||
&ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
161
libffi/src/s390/sysv.S
Normal file
161
libffi/src/s390/sysv.S
Normal file
@@ -0,0 +1,161 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 2000 Software AG
|
||||
|
||||
S390 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 CYGNUS SOLUTIONS 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 <ffi.h>
|
||||
#ifdef HAVE_MACHINE_ASM_H
|
||||
#include <machine/asm.h>
|
||||
#endif
|
||||
|
||||
.text
|
||||
|
||||
# r2: ffi_prep_args
|
||||
# r3: &ecif
|
||||
# r4: cif->bytes
|
||||
# r5: fig->flags
|
||||
# r6: ecif.rvalue
|
||||
# sp+0: fn
|
||||
|
||||
# This assumes we are using gas.
|
||||
.globl ffi_call_SYSV
|
||||
.type ffi_call_SYSV,%function
|
||||
ffi_call_SYSV:
|
||||
# Save registers
|
||||
stm %r7,%r15,28(%r15)
|
||||
l %r7,96(%r15) # Get A(fn)
|
||||
lr %r0,%r15
|
||||
ahi %r15,-128 # Make room for my args
|
||||
st %r0,0(%r15) # Set backchain
|
||||
lr %r11,%r15 # Establish my stack register
|
||||
sr %r15,%r4 # Make room for fn args
|
||||
ahi %r15,-96 # Make room for new frame
|
||||
lr %r10,%r15 # Establish stack build area
|
||||
ahi %r15,-96 # Stack for next call
|
||||
lr %r1,%r7
|
||||
stm %r2,%r7,96(%r11) # Save args on my stack
|
||||
|
||||
#------------------------------------------------------------------
|
||||
# move first 3 parameters in registers
|
||||
#------------------------------------------------------------------
|
||||
lr %r9,%r2 # r9: &ffi_prep_args
|
||||
lr %r2,%r10 # Parm 1: &stack Parm 2: &ecif
|
||||
basr %r14,%r9 # call ffi_prep_args
|
||||
|
||||
#------------------------------------------------------------------
|
||||
# load first 5 parameter registers
|
||||
#------------------------------------------------------------------
|
||||
lm %r2,%r6,24(%r10)
|
||||
|
||||
#------------------------------------------------------------------
|
||||
# load fp parameter registers
|
||||
#------------------------------------------------------------------
|
||||
ld %f0,48(%r10)
|
||||
ld %f2,56(%r10)
|
||||
|
||||
#------------------------------------------------------------------
|
||||
# call function
|
||||
#------------------------------------------------------------------
|
||||
lr %r15,%r10 # Set new stack
|
||||
l %r9,116(%r11) # Get &fn
|
||||
basr %r14,%r9 # Call function
|
||||
|
||||
#------------------------------------------------------------------
|
||||
# On return:
|
||||
# r2: Return value (r3: Return value + 4 for long long)
|
||||
#------------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------------
|
||||
# If the return value pointer is NULL, assume no return value.
|
||||
#------------------------------------------------------------------
|
||||
icm %r6,15,112(%r11)
|
||||
jz .Lepilogue
|
||||
|
||||
l %r5,108(%r11) # Get return type
|
||||
#------------------------------------------------------------------
|
||||
# return INT
|
||||
#------------------------------------------------------------------
|
||||
chi %r5,FFI_TYPE_INT
|
||||
jne .Lchk64
|
||||
|
||||
st %r2,0(%r6)
|
||||
j .Lepilogue
|
||||
|
||||
.Lchk64:
|
||||
#------------------------------------------------------------------
|
||||
# return LONG LONG (signed/unsigned)
|
||||
#------------------------------------------------------------------
|
||||
chi %r5,FFI_TYPE_UINT64
|
||||
je .LdoLongLong
|
||||
|
||||
chi %r5,FFI_TYPE_SINT64
|
||||
jne .LchkFloat
|
||||
|
||||
.LdoLongLong:
|
||||
stm %r2,%r3,0(%r6)
|
||||
j .Lepilogue
|
||||
|
||||
.LchkFloat:
|
||||
#------------------------------------------------------------------
|
||||
# return FLOAT
|
||||
#------------------------------------------------------------------
|
||||
chi %r5,FFI_TYPE_FLOAT
|
||||
jne .LchkDouble
|
||||
|
||||
std %f0,0(%r6)
|
||||
j .Lepilogue
|
||||
|
||||
.LchkDouble:
|
||||
#------------------------------------------------------------------
|
||||
# return DOUBLE or LONGDOUBLE
|
||||
#------------------------------------------------------------------
|
||||
chi %r5,FFI_TYPE_DOUBLE
|
||||
jne .LchkStruct
|
||||
|
||||
std %f0,0(%r6)
|
||||
std %f2,8(%r6)
|
||||
j .Lepilogue
|
||||
|
||||
.LchkStruct:
|
||||
#------------------------------------------------------------------
|
||||
# Structure - rvalue already set as sent as 1st parm to routine
|
||||
#------------------------------------------------------------------
|
||||
chi %r5,FFI_TYPE_STRUCT
|
||||
je .Lepilogue
|
||||
|
||||
.Ldefault:
|
||||
#------------------------------------------------------------------
|
||||
# return a pointer
|
||||
#------------------------------------------------------------------
|
||||
st %r2,0(%r6)
|
||||
j .Lepilogue
|
||||
|
||||
.Lepilogue:
|
||||
l %r15,0(%r11)
|
||||
l %r4,56(%r15)
|
||||
lm %r7,%r15,28(%r15)
|
||||
br %r4
|
||||
|
||||
.ffi_call_SYSV_end:
|
||||
.size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
Sparc Foreign Function Interface
|
||||
|
||||
$Id: ffi.c,v 1.1 1998/11/29 16:48:16 green Exp $
|
||||
|
||||
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
|
||||
@@ -33,7 +31,7 @@
|
||||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
has been allocated for the function's arguments */
|
||||
|
||||
void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
void ffi_prep_args_v8(char *stack, extended_cif *ecif)
|
||||
{
|
||||
int i;
|
||||
int tmp;
|
||||
@@ -45,16 +43,16 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
tmp = 0;
|
||||
|
||||
/* Skip 16 words for the window save area */
|
||||
argp = stack + 16*sizeof(void*);
|
||||
argp = stack + 16*sizeof(int);
|
||||
|
||||
/* This should only really be done when we are returning a structure,
|
||||
however, it's faster just to do it all the time...
|
||||
|
||||
if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) */
|
||||
*(void **) argp = ecif->rvalue;
|
||||
*(int *) argp = (long)ecif->rvalue;
|
||||
|
||||
/* And 1 word for the structure return value. */
|
||||
argp += sizeof(void*);
|
||||
argp += sizeof(int);
|
||||
|
||||
#ifdef USING_PURIFY
|
||||
/* Purify will probably complain in our assembly routine, unless we
|
||||
@@ -81,10 +79,13 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
{
|
||||
avn--;
|
||||
if ((*p_arg)->type == FFI_TYPE_STRUCT
|
||||
|| (*p_arg)->type == FFI_TYPE_LONGDOUBLE)
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
|| (*p_arg)->type == FFI_TYPE_LONGDOUBLE
|
||||
#endif
|
||||
)
|
||||
{
|
||||
*(unsigned int *) argp = (unsigned int)(* p_argv);
|
||||
z = sizeof(void*);
|
||||
*(unsigned int *) argp = (unsigned long)(* p_argv);
|
||||
z = sizeof(int);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -109,15 +110,7 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = *(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
*(signed int *) argp = *(SINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
*(unsigned int *) argp = *(UINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
@@ -135,82 +128,295 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
return;
|
||||
}
|
||||
|
||||
int ffi_prep_args_v9(char *stack, extended_cif *ecif)
|
||||
{
|
||||
int i, ret = 0;
|
||||
int tmp;
|
||||
void **p_argv;
|
||||
char *argp;
|
||||
ffi_type **p_arg;
|
||||
|
||||
tmp = 0;
|
||||
|
||||
/* Skip 16 words for the window save area */
|
||||
argp = stack + 16*sizeof(long long);
|
||||
|
||||
#ifdef USING_PURIFY
|
||||
/* Purify will probably complain in our assembly routine, unless we
|
||||
zero out this memory. */
|
||||
|
||||
((long long*)argp)[0] = 0;
|
||||
((long long*)argp)[1] = 0;
|
||||
((long long*)argp)[2] = 0;
|
||||
((long long*)argp)[3] = 0;
|
||||
((long long*)argp)[4] = 0;
|
||||
((long long*)argp)[5] = 0;
|
||||
#endif
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT &&
|
||||
ecif->cif->rtype->size > 32)
|
||||
{
|
||||
*(unsigned long long *) argp = (unsigned long)ecif->rvalue;
|
||||
tmp = 1;
|
||||
}
|
||||
|
||||
for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs;
|
||||
i++, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
z = (*p_arg)->size;
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_STRUCT:
|
||||
if (z > 16)
|
||||
{
|
||||
/* For structures larger than 16 bytes we pass reference. */
|
||||
*(unsigned long long *) argp = (unsigned long)* p_argv;
|
||||
argp += sizeof(long long);
|
||||
tmp++;
|
||||
p_argv++;
|
||||
continue;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
#endif
|
||||
ret = 1; /* We should promote into FP regs as well as integer. */
|
||||
break;
|
||||
}
|
||||
if (z < sizeof(long long))
|
||||
{
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed long long *) argp = *(SINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned long long *) argp = *(UINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed long long *) argp = *(SINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned long long *) argp = *(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
*(signed long long *) argp = *(SINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
*(unsigned long long *) argp = *(UINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
*(float *) (argp + 4) = *(FLOAT32 *)(* p_argv); /* Right justify */
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
memcpy(argp, *p_argv, z);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
z = sizeof(long long);
|
||||
tmp++;
|
||||
}
|
||||
else if (z == sizeof(long long))
|
||||
{
|
||||
memcpy(argp, *p_argv, z);
|
||||
z = sizeof(long long);
|
||||
tmp++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((tmp & 1) && (*p_arg)->alignment > 8)
|
||||
{
|
||||
tmp++;
|
||||
argp += sizeof(long long);
|
||||
}
|
||||
memcpy(argp, *p_argv, z);
|
||||
z = 2 * sizeof(long long);
|
||||
tmp += 2;
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
/* If we are returning a struct, this will already have been added.
|
||||
Otherwise we need to add it because it's always got to be there! */
|
||||
int wordsize;
|
||||
|
||||
if (cif->rtype->type != FFI_TYPE_STRUCT)
|
||||
cif->bytes += sizeof(void*);
|
||||
if (cif->abi != FFI_V9)
|
||||
{
|
||||
wordsize = 4;
|
||||
|
||||
/* sparc call frames require that space is allocated for 6 args,
|
||||
even if they aren't used. Make that space if necessary. */
|
||||
/* If we are returning a struct, this will already have been added.
|
||||
Otherwise we need to add it because it's always got to be there! */
|
||||
|
||||
if (cif->rtype->type != FFI_TYPE_STRUCT)
|
||||
cif->bytes += wordsize;
|
||||
|
||||
/* sparc call frames require that space is allocated for 6 args,
|
||||
even if they aren't used. Make that space if necessary. */
|
||||
|
||||
if (cif->bytes < 4*6+4)
|
||||
cif->bytes = 4*6+4;
|
||||
if (cif->bytes < 4*6+4)
|
||||
cif->bytes = 4*6+4;
|
||||
}
|
||||
else
|
||||
{
|
||||
wordsize = 8;
|
||||
|
||||
/* sparc call frames require that space is allocated for 6 args,
|
||||
even if they aren't used. Make that space if necessary. */
|
||||
|
||||
if (cif->bytes < 8*6)
|
||||
cif->bytes = 8*6;
|
||||
}
|
||||
|
||||
/* Adjust cif->bytes. to include 16 words for the window save area,
|
||||
and maybe the struct/union return pointer area, */
|
||||
|
||||
cif->bytes += 64;
|
||||
cif->bytes += 16 * wordsize;
|
||||
|
||||
/* The stack must be double word aligned, so round bytes up
|
||||
/* The stack must be 2 word aligned, so round bytes up
|
||||
appropriately. */
|
||||
|
||||
cif->bytes = ALIGN(cif->bytes, 2*sizeof(void*));
|
||||
cif->bytes = ALIGN(cif->bytes, 2 * wordsize);
|
||||
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_STRUCT:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
#endif
|
||||
cif->flags = cif->rtype->type;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
cif->flags = FFI_TYPE_FLOAT;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags = FFI_TYPE_DOUBLE;
|
||||
case FFI_TYPE_STRUCT:
|
||||
if (cif->abi == FFI_V9 && cif->rtype->size > 32)
|
||||
cif->flags = FFI_TYPE_VOID;
|
||||
else
|
||||
cif->flags = FFI_TYPE_STRUCT;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
if (cif->abi != FFI_V9)
|
||||
{
|
||||
cif->flags = FFI_TYPE_SINT64;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
int ffi_V9_return_struct(ffi_type *arg, int off, char *ret, char *intg, char *flt)
|
||||
{
|
||||
ffi_type **ptr = &arg->elements[0];
|
||||
|
||||
while (*ptr != NULL)
|
||||
{
|
||||
if (off & ((*ptr)->alignment - 1))
|
||||
off = ALIGN(off, (*ptr)->alignment);
|
||||
|
||||
switch ((*ptr)->type)
|
||||
{
|
||||
case FFI_TYPE_STRUCT:
|
||||
off = ffi_V9_return_struct(*ptr, off, ret, intg, flt);
|
||||
break;
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
#endif
|
||||
memcpy(ret + off, flt + off, (*ptr)->size);
|
||||
off += (*ptr)->size;
|
||||
break;
|
||||
default:
|
||||
memcpy(ret + off, intg + off, (*ptr)->size);
|
||||
off += (*ptr)->size;
|
||||
break;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
return off;
|
||||
}
|
||||
|
||||
extern int ffi_call_V8(void *, extended_cif *, unsigned,
|
||||
unsigned, unsigned *, void (*fn)());
|
||||
extern int ffi_call_V9(void *, extended_cif *, unsigned,
|
||||
unsigned, unsigned *, void (*fn)());
|
||||
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
void *rval = rvalue;
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
|
||||
/* 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))
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
|
||||
ecif.rvalue = rvalue;
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
if (cif->rtype->size <= 32)
|
||||
rval = alloca(64);
|
||||
else
|
||||
{
|
||||
rval = NULL;
|
||||
if (rvalue == NULL)
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
}
|
||||
}
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_V8:
|
||||
ffi_call_V8(ffi_prep_args, &ecif, cif->bytes,
|
||||
#ifdef SPARC64
|
||||
/* We don't yet support calling 32bit code from 64bit */
|
||||
FFI_ASSERT(0);
|
||||
#else
|
||||
ffi_call_V8(ffi_prep_args_v8, &ecif, cif->bytes,
|
||||
cif->flags, rvalue, fn);
|
||||
#endif
|
||||
break;
|
||||
case FFI_V9:
|
||||
#ifdef SPARC64
|
||||
ffi_call_V9(ffi_prep_args_v9, &ecif, cif->bytes,
|
||||
cif->flags, rval, fn);
|
||||
if (rvalue && rval && cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
ffi_V9_return_struct(cif->rtype, 0, (char *)rvalue, (char *)rval, ((char *)rval)+32);
|
||||
#else
|
||||
/* And vice versa */
|
||||
FFI_ASSERT(0);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
Sparc Foreign Function Interface
|
||||
|
||||
$Id: v8.S,v 1.1 1998/11/29 16:48:16 green Exp $
|
||||
|
||||
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
|
||||
@@ -56,6 +54,7 @@ _ffi_call_V8:
|
||||
ld [%l0+ARGS+20], %o5
|
||||
call %i5
|
||||
mov %l0, %sp ! (delay) switch to frame
|
||||
nop ! STRUCT returning functions skip 12 instead of 8 bytes
|
||||
|
||||
! If the return value pointer is NULL, assume no return value.
|
||||
tst %i4
|
||||
@@ -70,6 +69,9 @@ _ffi_call_V8:
|
||||
be,a done
|
||||
st %f0, [%i4+0] ! (delay)
|
||||
|
||||
cmp %i3, FFI_TYPE_SINT64
|
||||
be longlong
|
||||
|
||||
cmp %i3, FFI_TYPE_DOUBLE
|
||||
bne done
|
||||
nop
|
||||
@@ -80,6 +82,12 @@ done:
|
||||
ret
|
||||
restore
|
||||
|
||||
longlong:
|
||||
st %o0, [%i4+0]
|
||||
st %o1, [%i4+4]
|
||||
ret
|
||||
restore
|
||||
|
||||
.ffi_call_V8_end:
|
||||
.size ffi_call_V8,.ffi_call_V8_end-ffi_call_V8
|
||||
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
Sparc 64bit Foreign Function Interface
|
||||
|
||||
$Id: v9.S,v 1.1 2000/04/17 03:18:46 green Exp $
|
||||
|
||||
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
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
Predefined ffi_types needed by libffi.
|
||||
|
||||
$Id: types.c,v 1.1 1998/11/29 16:48:16 green Exp $
|
||||
|
||||
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
|
||||
@@ -19,7 +17,7 @@
|
||||
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 CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
IN NO EVENT SHALL RED HAT 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.
|
||||
@@ -42,15 +40,28 @@ FFI_INTEGRAL_TYPEDEF(uint16, 2, 2, FFI_TYPE_UINT16);
|
||||
FFI_INTEGRAL_TYPEDEF(sint16, 2, 2, FFI_TYPE_SINT16);
|
||||
FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32);
|
||||
FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32);
|
||||
FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER);
|
||||
FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT);
|
||||
|
||||
#if defined ALPHA || defined SPARC64
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER);
|
||||
|
||||
#else
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef X86
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
|
||||
FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
|
||||
|
||||
#elif defined X86_WIN32
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
|
||||
FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
|
||||
|
||||
#elif defined ARM
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
|
||||
@@ -74,6 +85,11 @@ FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64);
|
||||
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
|
||||
|
||||
#elif defined X86_WIN32
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
|
||||
|
||||
#elif defined ARM
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
|
||||
@@ -87,8 +103,17 @@ FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
|
||||
#elif defined SPARC
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
|
||||
|
||||
#ifdef SPARC64
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
|
||||
|
||||
#else
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 8, FFI_TYPE_LONGDOUBLE);
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
x86 Foreign Function Interface
|
||||
|
||||
$Id: ffi.c,v 1.3 1999/08/08 13:05:12 green Exp $
|
||||
|
||||
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
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
X86 Foreign Function Interface
|
||||
|
||||
$Id: sysv.S,v 1.2 1999/08/04 18:00:05 green Exp $
|
||||
|
||||
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
|
||||
@@ -38,9 +36,11 @@
|
||||
.type ffi_call_SYSV,@function
|
||||
|
||||
ffi_call_SYSV:
|
||||
.LFB1:
|
||||
pushl %ebp
|
||||
.LCFI0:
|
||||
movl %esp,%ebp
|
||||
|
||||
.LCFI1:
|
||||
# Make room for all of the new args.
|
||||
movl 16(%ebp),%ecx
|
||||
subl %ecx,%esp
|
||||
@@ -124,6 +124,43 @@ epilogue:
|
||||
movl %ebp,%esp
|
||||
popl %ebp
|
||||
ret
|
||||
.LFE1:
|
||||
.ffi_call_SYSV_end:
|
||||
.size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
|
||||
|
||||
.section .eh_frame,"aw",@progbits
|
||||
__FRAME_BEGIN__:
|
||||
.4byte .LLCIE1
|
||||
.LSCIE1:
|
||||
.4byte 0x0
|
||||
.byte 0x1
|
||||
.byte 0x0
|
||||
.byte 0x1
|
||||
.byte 0x7c
|
||||
.byte 0x8
|
||||
.byte 0xc
|
||||
.byte 0x4
|
||||
.byte 0x4
|
||||
.byte 0x88
|
||||
.byte 0x1
|
||||
.align 4
|
||||
.LECIE1:
|
||||
.set .LLCIE1,.LECIE1-.LSCIE1
|
||||
.4byte .LLFDE1
|
||||
.LSFDE1:
|
||||
.4byte .LSFDE1-__FRAME_BEGIN__
|
||||
.4byte .LFB1
|
||||
.4byte .LFE1-.LFB1
|
||||
.byte 0x4
|
||||
.4byte .LCFI0-.LFB1
|
||||
.byte 0xe
|
||||
.byte 0x8
|
||||
.byte 0x85
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.4byte .LCFI1-.LCFI0
|
||||
.byte 0xd
|
||||
.byte 0x5
|
||||
.align 4
|
||||
.LEFDE1:
|
||||
.set .LLFDE1,.LEFDE1-.LSFDE1
|
||||
|
||||
125
libffi/src/x86/win32.S
Normal file
125
libffi/src/x86/win32.S
Normal file
@@ -0,0 +1,125 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
win32.S - Copyright (c) 1996, 1998, 2001 Cygnus Solutions
|
||||
|
||||
X86 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 CYGNUS SOLUTIONS 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 <ffi.h>
|
||||
|
||||
.text
|
||||
|
||||
.globl ffi_prep_args
|
||||
|
||||
# This assumes we are using gas.
|
||||
.balign 16
|
||||
.globl _ffi_call_SYSV
|
||||
|
||||
_ffi_call_SYSV:
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
|
||||
# Make room for all of the new args.
|
||||
movl 16(%ebp),%ecx
|
||||
subl %ecx,%esp
|
||||
|
||||
movl %esp,%eax
|
||||
|
||||
# Place all of the ffi_prep_args in position
|
||||
pushl 12(%ebp)
|
||||
pushl %eax
|
||||
call *8(%ebp)
|
||||
|
||||
# Return stack to previous state and call the function
|
||||
addl $8,%esp
|
||||
|
||||
call *28(%ebp)
|
||||
|
||||
# Remove the space we pushed for the args
|
||||
movl 16(%ebp),%ecx
|
||||
addl %ecx,%esp
|
||||
|
||||
# Load %ecx with the return type code
|
||||
movl 20(%ebp),%ecx
|
||||
|
||||
# If the return value pointer is NULL, assume no return value.
|
||||
cmpl $0,24(%ebp)
|
||||
jne retint
|
||||
|
||||
# Even if there is no space for the return value, we are
|
||||
# obliged to handle floating-point values.
|
||||
cmpl $FFI_TYPE_FLOAT,%ecx
|
||||
jne noretval
|
||||
fstp %st(0)
|
||||
|
||||
jmp epilogue
|
||||
|
||||
retint:
|
||||
cmpl $FFI_TYPE_INT,%ecx
|
||||
jne retfloat
|
||||
# Load %ecx with the pointer to storage for the return value
|
||||
movl 24(%ebp),%ecx
|
||||
movl %eax,0(%ecx)
|
||||
jmp epilogue
|
||||
|
||||
retfloat:
|
||||
cmpl $FFI_TYPE_FLOAT,%ecx
|
||||
jne retdouble
|
||||
# Load %ecx with the pointer to storage for the return value
|
||||
movl 24(%ebp),%ecx
|
||||
fstps (%ecx)
|
||||
jmp epilogue
|
||||
|
||||
retdouble:
|
||||
cmpl $FFI_TYPE_DOUBLE,%ecx
|
||||
jne retlongdouble
|
||||
# Load %ecx with the pointer to storage for the return value
|
||||
movl 24(%ebp),%ecx
|
||||
fstpl (%ecx)
|
||||
jmp epilogue
|
||||
|
||||
retlongdouble:
|
||||
cmpl $FFI_TYPE_LONGDOUBLE,%ecx
|
||||
jne retint64
|
||||
# Load %ecx with the pointer to storage for the return value
|
||||
movl 24(%ebp),%ecx
|
||||
fstpt (%ecx)
|
||||
jmp epilogue
|
||||
|
||||
retint64:
|
||||
cmpl $FFI_TYPE_SINT64,%ecx
|
||||
jne retstruct
|
||||
# Load %ecx with the pointer to storage for the return value
|
||||
movl 24(%ebp),%ecx
|
||||
movl %eax,0(%ecx)
|
||||
movl %edx,4(%ecx)
|
||||
|
||||
retstruct:
|
||||
# Nothing to do!
|
||||
|
||||
noretval:
|
||||
epilogue:
|
||||
movl %ebp,%esp
|
||||
popl %ebp
|
||||
ret
|
||||
|
||||
.ffi_call_SYSV_end:
|
||||
Reference in New Issue
Block a user