re PR libffi/28313 (libffi has not been ported to mips64-linux-gnu)
PR libffi/28313 * configure.ac: Don't treat mips64 as a special case. * Makefile.am (nodist_libffi_la_SOURCES): Add n32.S. * configure: Regenerate * Makefile.in: Ditto. * fficonfig.h.in: Ditto. * src/mips/ffitarget.h (REG_L, REG_S, SUBU, ADDU, SRL, LI): Indent. (LA, EH_FRAME_ALIGN, FDE_ADDR_BYTES): New preprocessor macros. (FFI_DEFAULT_ABI): Set for n64 case. (FFI_CLOSURES, FFI_TRAMPOLINE_SIZE): Define for n32 and n64 cases. * src/mips/n32.S (ffi_call_N32): Add debug macros and labels for FDE. (ffi_closure_N32): New function. (.eh_frame): New section * src/mips/o32.S: Clean up comments. (ffi_closure_O32): Pass ffi_closure parameter in $12. * src/mips/ffi.c: Use FFI_MIPS_N32 instead of _MIPS_SIM == _ABIN32 throughout. (FFI_MIPS_STOP_HERE): New, use in place of ffi_stop_here. (ffi_prep_args): Use unsigned long to hold pointer values. Rewrite to support n32/n64 ABIs. (calc_n32_struct_flags): Rewrite. (calc_n32_return_struct_flags): Remove unused variable. Reverse position of flag bits. (ffi_prep_cif_machdep): Rewrite n32 portion. (ffi_call): Enable for n64. Add special handling for small structure return values. (ffi_prep_closure_loc): Add n32 and n64 support. (ffi_closure_mips_inner_O32): Add cast to silence warning. (copy_struct_N32, ffi_closure_mips_inner_N32): New functions. From-SVN: r127336
This commit is contained in:
parent
2fbe0e5aec
commit
89d9d98ae5
10 changed files with 635 additions and 96 deletions
|
@ -1,3 +1,36 @@
|
|||
2007-08-10 David Daney <ddaney@avtrex.com>
|
||||
|
||||
PR libffi/28313
|
||||
* configure.ac: Don't treat mips64 as a special case.
|
||||
* Makefile.am (nodist_libffi_la_SOURCES): Add n32.S.
|
||||
* configure: Regenerate
|
||||
* Makefile.in: Ditto.
|
||||
* fficonfig.h.in: Ditto.
|
||||
* src/mips/ffitarget.h (REG_L, REG_S, SUBU, ADDU, SRL, LI): Indent.
|
||||
(LA, EH_FRAME_ALIGN, FDE_ADDR_BYTES): New preprocessor macros.
|
||||
(FFI_DEFAULT_ABI): Set for n64 case.
|
||||
(FFI_CLOSURES, FFI_TRAMPOLINE_SIZE): Define for n32 and n64 cases.
|
||||
* src/mips/n32.S (ffi_call_N32): Add debug macros and labels for FDE.
|
||||
(ffi_closure_N32): New function.
|
||||
(.eh_frame): New section
|
||||
* src/mips/o32.S: Clean up comments.
|
||||
(ffi_closure_O32): Pass ffi_closure parameter in $12.
|
||||
* src/mips/ffi.c: Use FFI_MIPS_N32 instead of
|
||||
_MIPS_SIM == _ABIN32 throughout.
|
||||
(FFI_MIPS_STOP_HERE): New, use in place of
|
||||
ffi_stop_here.
|
||||
(ffi_prep_args): Use unsigned long to hold pointer values. Rewrite
|
||||
to support n32/n64 ABIs.
|
||||
(calc_n32_struct_flags): Rewrite.
|
||||
(calc_n32_return_struct_flags): Remove unused variable. Reverse
|
||||
position of flag bits.
|
||||
(ffi_prep_cif_machdep): Rewrite n32 portion.
|
||||
(ffi_call): Enable for n64. Add special handling for small structure
|
||||
return values.
|
||||
(ffi_prep_closure_loc): Add n32 and n64 support.
|
||||
(ffi_closure_mips_inner_O32): Add cast to silence warning.
|
||||
(copy_struct_N32, ffi_closure_mips_inner_N32): New functions.
|
||||
|
||||
2007-08-08 David Daney <ddaney@avtrex.com>
|
||||
|
||||
* testsuite/libffi.call/ffitest.h (ffi_type_mylong): Remove definition.
|
||||
|
|
|
@ -88,7 +88,7 @@ if MIPS_IRIX
|
|||
nodist_libffi_la_SOURCES += src/mips/ffi.c src/mips/o32.S src/mips/n32.S
|
||||
endif
|
||||
if MIPS_LINUX
|
||||
nodist_libffi_la_SOURCES += src/mips/ffi.c src/mips/o32.S
|
||||
nodist_libffi_la_SOURCES += src/mips/ffi.c src/mips/o32.S src/mips/n32.S
|
||||
endif
|
||||
if X86
|
||||
nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/sysv.S
|
||||
|
|
|
@ -38,7 +38,7 @@ build_triplet = @build@
|
|||
host_triplet = @host@
|
||||
target_triplet = @target@
|
||||
@MIPS_IRIX_TRUE@am__append_1 = src/mips/ffi.c src/mips/o32.S src/mips/n32.S
|
||||
@MIPS_LINUX_TRUE@am__append_2 = src/mips/ffi.c src/mips/o32.S
|
||||
@MIPS_LINUX_TRUE@am__append_2 = src/mips/ffi.c src/mips/o32.S src/mips/n32.S
|
||||
@X86_TRUE@am__append_3 = src/x86/ffi.c src/x86/sysv.S
|
||||
@X86_WIN32_TRUE@am__append_4 = src/x86/ffi.c src/x86/win32.S
|
||||
@X86_DARWIN_TRUE@am__append_5 = src/x86/ffi.c src/x86/darwin.S src/x86/ffi64.c src/x86/darwin64.S
|
||||
|
@ -97,7 +97,8 @@ am_libffi_la_OBJECTS = src/debug.lo src/prep_cif.lo src/types.lo \
|
|||
src/raw_api.lo src/java_raw_api.lo src/closures.lo
|
||||
@MIPS_IRIX_TRUE@am__objects_1 = src/mips/ffi.lo src/mips/o32.lo \
|
||||
@MIPS_IRIX_TRUE@ src/mips/n32.lo
|
||||
@MIPS_LINUX_TRUE@am__objects_2 = src/mips/ffi.lo src/mips/o32.lo
|
||||
@MIPS_LINUX_TRUE@am__objects_2 = src/mips/ffi.lo src/mips/o32.lo \
|
||||
@MIPS_LINUX_TRUE@ src/mips/n32.lo
|
||||
@X86_TRUE@am__objects_3 = src/x86/ffi.lo src/x86/sysv.lo
|
||||
@X86_WIN32_TRUE@am__objects_4 = src/x86/ffi.lo src/x86/win32.lo
|
||||
@X86_DARWIN_TRUE@am__objects_5 = src/x86/ffi.lo src/x86/darwin.lo \
|
||||
|
|
2
libffi/configure
vendored
2
libffi/configure
vendored
|
@ -10324,8 +10324,6 @@ case "$host" in
|
|||
TARGET=M68K; TARGETDIR=m68k
|
||||
;;
|
||||
|
||||
mips64*-*)
|
||||
;;
|
||||
mips-sgi-irix5.* | mips-sgi-irix6.*)
|
||||
TARGET=MIPS_IRIX; TARGETDIR=mips
|
||||
;;
|
||||
|
|
|
@ -94,8 +94,6 @@ case "$host" in
|
|||
TARGET=M68K; TARGETDIR=m68k
|
||||
;;
|
||||
|
||||
mips64*-*)
|
||||
;;
|
||||
mips-sgi-irix5.* | mips-sgi-irix6.*)
|
||||
TARGET=MIPS_IRIX; TARGETDIR=mips
|
||||
;;
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
*/
|
||||
#undef HAVE_AS_SPARC_UA_PCREL
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* Define if __attribute__((visibility("hidden"))) is supported. */
|
||||
#undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
|
||||
|
||||
|
@ -91,6 +94,10 @@
|
|||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#undef LT_OBJDIR
|
||||
|
||||
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
|
||||
#undef NO_MINUS_C_MINUS_O
|
||||
|
||||
|
|
|
@ -28,13 +28,19 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
#if _MIPS_SIM == _ABIN32
|
||||
#ifdef FFI_DEBUG
|
||||
# define FFI_MIPS_STOP_HERE() ffi_stop_here()
|
||||
#else
|
||||
# define FFI_MIPS_STOP_HERE() do {} while(0)
|
||||
#endif
|
||||
|
||||
#ifdef FFI_MIPS_N32
|
||||
#define FIX_ARGP \
|
||||
FFI_ASSERT(argp <= &stack[bytes]); \
|
||||
if (argp == &stack[bytes]) \
|
||||
{ \
|
||||
argp = stack; \
|
||||
ffi_stop_here(); \
|
||||
FFI_MIPS_STOP_HERE(); \
|
||||
}
|
||||
#else
|
||||
#define FIX_ARGP
|
||||
|
@ -54,7 +60,7 @@ static void ffi_prep_args(char *stack,
|
|||
char *argp;
|
||||
ffi_type **p_arg;
|
||||
|
||||
#if _MIPS_SIM == _ABIN32
|
||||
#ifdef FFI_MIPS_N32
|
||||
/* If more than 8 double words are used, the remainder go
|
||||
on the stack. We reorder stuff on the stack here to
|
||||
support this easily. */
|
||||
|
@ -68,7 +74,7 @@ static void ffi_prep_args(char *stack,
|
|||
|
||||
memset(stack, 0, bytes);
|
||||
|
||||
#if _MIPS_SIM == _ABIN32
|
||||
#ifdef FFI_MIPS_N32
|
||||
if ( ecif->cif->rstruct_flag != 0 )
|
||||
#else
|
||||
if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT )
|
||||
|
@ -91,7 +97,7 @@ static void ffi_prep_args(char *stack,
|
|||
if (a < sizeof(ffi_arg))
|
||||
a = sizeof(ffi_arg);
|
||||
|
||||
if ((a - 1) & (unsigned int) argp)
|
||||
if ((a - 1) & (unsigned long) argp)
|
||||
{
|
||||
argp = (char *) ALIGN(argp, a);
|
||||
FIX_ARGP;
|
||||
|
@ -100,9 +106,15 @@ static void ffi_prep_args(char *stack,
|
|||
z = (*p_arg)->size;
|
||||
if (z <= sizeof(ffi_arg))
|
||||
{
|
||||
int type = (*p_arg)->type;
|
||||
z = sizeof(ffi_arg);
|
||||
|
||||
switch ((*p_arg)->type)
|
||||
/* The size of a pointer depends on the ABI */
|
||||
if (type == FFI_TYPE_POINTER)
|
||||
type =
|
||||
(ecif->cif->abi == FFI_N64) ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(ffi_arg *)argp = *(SINT8 *)(* p_argv);
|
||||
|
@ -125,7 +137,6 @@ static void ffi_prep_args(char *stack,
|
|||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_POINTER:
|
||||
*(ffi_arg *)argp = *(UINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
|
@ -134,8 +145,7 @@ static void ffi_prep_args(char *stack,
|
|||
*(float *) argp = *(float *)(* p_argv);
|
||||
break;
|
||||
|
||||
/* Handle small structures. */
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* Handle structures. */
|
||||
default:
|
||||
memcpy(argp, *p_argv, (*p_arg)->size);
|
||||
break;
|
||||
|
@ -143,12 +153,12 @@ static void ffi_prep_args(char *stack,
|
|||
}
|
||||
else
|
||||
{
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
#ifdef FFI_MIPS_O32
|
||||
memcpy(argp, *p_argv, z);
|
||||
#else
|
||||
{
|
||||
unsigned end = (unsigned) argp+z;
|
||||
unsigned cap = (unsigned) stack+bytes;
|
||||
unsigned long end = (unsigned long) argp + z;
|
||||
unsigned long cap = (unsigned long) stack + bytes;
|
||||
|
||||
/* Check if the data will fit within the register space.
|
||||
Handle it if it doesn't. */
|
||||
|
@ -157,12 +167,13 @@ static void ffi_prep_args(char *stack,
|
|||
memcpy(argp, *p_argv, z);
|
||||
else
|
||||
{
|
||||
unsigned portion = end - cap;
|
||||
unsigned long portion = cap - (unsigned long)argp;
|
||||
|
||||
memcpy(argp, *p_argv, portion);
|
||||
argp = stack;
|
||||
memcpy(argp,
|
||||
(void*)((unsigned)(*p_argv)+portion), z - portion);
|
||||
z -= portion;
|
||||
memcpy(argp, (void*)((unsigned long)(*p_argv) + portion),
|
||||
z);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -173,7 +184,7 @@ static void ffi_prep_args(char *stack,
|
|||
}
|
||||
}
|
||||
|
||||
#if _MIPS_SIM == _ABIN32
|
||||
#ifdef FFI_MIPS_N32
|
||||
|
||||
/* The n32 spec says that if "a chunk consists solely of a double
|
||||
float field (but not a double, which is part of a union), it
|
||||
|
@ -181,35 +192,41 @@ static void ffi_prep_args(char *stack,
|
|||
passed in an integer register". This code traverses structure
|
||||
definitions and generates the appropriate flags. */
|
||||
|
||||
unsigned calc_n32_struct_flags(ffi_type *arg, unsigned *shift)
|
||||
static unsigned
|
||||
calc_n32_struct_flags(ffi_type *arg, unsigned *loc, unsigned *arg_reg)
|
||||
{
|
||||
unsigned flags = 0;
|
||||
unsigned index = 0;
|
||||
|
||||
ffi_type *e;
|
||||
|
||||
while (e = arg->elements[index])
|
||||
while ((e = arg->elements[index]))
|
||||
{
|
||||
/* Align this object. */
|
||||
*loc = ALIGN(*loc, e->alignment);
|
||||
if (e->type == FFI_TYPE_DOUBLE)
|
||||
{
|
||||
flags += (FFI_TYPE_DOUBLE << *shift);
|
||||
*shift += FFI_FLAG_BITS;
|
||||
/* Already aligned to FFI_SIZEOF_ARG. */
|
||||
*arg_reg = *loc / FFI_SIZEOF_ARG;
|
||||
if (*arg_reg > 7)
|
||||
break;
|
||||
flags += (FFI_TYPE_DOUBLE << (*arg_reg * FFI_FLAG_BITS));
|
||||
*loc += e->size;
|
||||
}
|
||||
else if (e->type == FFI_TYPE_STRUCT)
|
||||
flags += calc_n32_struct_flags(e, shift);
|
||||
else
|
||||
*shift += FFI_FLAG_BITS;
|
||||
|
||||
*loc += e->size;
|
||||
index++;
|
||||
}
|
||||
/* Next Argument register at alignment of FFI_SIZEOF_ARG. */
|
||||
*arg_reg = ALIGN(*loc, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
unsigned calc_n32_return_struct_flags(ffi_type *arg)
|
||||
static unsigned
|
||||
calc_n32_return_struct_flags(ffi_type *arg)
|
||||
{
|
||||
unsigned flags = 0;
|
||||
unsigned index = 0;
|
||||
unsigned small = FFI_TYPE_SMALLSTRUCT;
|
||||
ffi_type *e;
|
||||
|
||||
|
@ -228,16 +245,16 @@ unsigned calc_n32_return_struct_flags(ffi_type *arg)
|
|||
|
||||
e = arg->elements[0];
|
||||
if (e->type == FFI_TYPE_DOUBLE)
|
||||
flags = FFI_TYPE_DOUBLE << FFI_FLAG_BITS;
|
||||
flags = FFI_TYPE_DOUBLE;
|
||||
else if (e->type == FFI_TYPE_FLOAT)
|
||||
flags = FFI_TYPE_FLOAT << FFI_FLAG_BITS;
|
||||
flags = FFI_TYPE_FLOAT;
|
||||
|
||||
if (flags && (e = arg->elements[1]))
|
||||
{
|
||||
if (e->type == FFI_TYPE_DOUBLE)
|
||||
flags += FFI_TYPE_DOUBLE;
|
||||
flags += FFI_TYPE_DOUBLE << FFI_FLAG_BITS;
|
||||
else if (e->type == FFI_TYPE_FLOAT)
|
||||
flags += FFI_TYPE_FLOAT;
|
||||
flags += FFI_TYPE_FLOAT << FFI_FLAG_BITS;
|
||||
else
|
||||
return small;
|
||||
|
||||
|
@ -262,7 +279,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
{
|
||||
cif->flags = 0;
|
||||
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
#ifdef FFI_MIPS_O32
|
||||
/* Set the flags necessary for O32 processing. FFI_O32_SOFT_FLOAT
|
||||
* does not have special handling for floating point args.
|
||||
*/
|
||||
|
@ -350,10 +367,11 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if _MIPS_SIM == _ABIN32
|
||||
#ifdef FFI_MIPS_N32
|
||||
/* Set the flags necessary for N32 processing */
|
||||
{
|
||||
unsigned shift = 0;
|
||||
unsigned arg_reg = 0;
|
||||
unsigned loc = 0;
|
||||
unsigned count = (cif->nargs < 8) ? cif->nargs : 8;
|
||||
unsigned index = 0;
|
||||
|
||||
|
@ -368,7 +386,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
/* This means that the structure is being passed as
|
||||
a hidden argument */
|
||||
|
||||
shift = FFI_FLAG_BITS;
|
||||
arg_reg = 1;
|
||||
count = (cif->nargs < 7) ? cif->nargs : 7;
|
||||
|
||||
cif->rstruct_flag = !0;
|
||||
|
@ -379,23 +397,37 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
else
|
||||
cif->rstruct_flag = 0;
|
||||
|
||||
while (count-- > 0)
|
||||
while (count-- > 0 && arg_reg < 8)
|
||||
{
|
||||
switch ((cif->arg_types)[index]->type)
|
||||
{
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags += ((cif->arg_types)[index]->type << shift);
|
||||
shift += FFI_FLAG_BITS;
|
||||
cif->flags +=
|
||||
((cif->arg_types)[index]->type << (arg_reg * FFI_FLAG_BITS));
|
||||
arg_reg++;
|
||||
break;
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* Align it. */
|
||||
arg_reg = ALIGN(arg_reg, 2);
|
||||
/* Treat it as two adjacent doubles. */
|
||||
cif->flags +=
|
||||
(FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
|
||||
arg_reg++;
|
||||
cif->flags +=
|
||||
(FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
|
||||
arg_reg++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
loc = arg_reg * FFI_SIZEOF_ARG;
|
||||
cif->flags += calc_n32_struct_flags((cif->arg_types)[index],
|
||||
&shift);
|
||||
&loc, &arg_reg);
|
||||
break;
|
||||
|
||||
default:
|
||||
shift += FFI_FLAG_BITS;
|
||||
arg_reg++;
|
||||
break;
|
||||
}
|
||||
|
||||
index++;
|
||||
|
@ -430,7 +462,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
|
||||
break;
|
||||
|
@ -469,7 +501,7 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
|
|||
|
||||
switch (cif->abi)
|
||||
{
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
#ifdef FFI_MIPS_O32
|
||||
case FFI_O32:
|
||||
case FFI_O32_SOFT_FLOAT:
|
||||
ffi_call_O32(ffi_prep_args, &ecif, cif->bytes,
|
||||
|
@ -477,10 +509,25 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
|
|||
break;
|
||||
#endif
|
||||
|
||||
#if _MIPS_SIM == _ABIN32
|
||||
#ifdef FFI_MIPS_N32
|
||||
case FFI_N32:
|
||||
ffi_call_N32(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
case FFI_N64:
|
||||
{
|
||||
int copy_rvalue = 0;
|
||||
void *rvalue_copy = ecif.rvalue;
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT && cif->rtype->size < 16)
|
||||
{
|
||||
/* For structures smaller than 16 bytes we clobber memory
|
||||
in 8 byte increments. Make a copy so we don't clobber
|
||||
the callers memory outside of the struct bounds. */
|
||||
rvalue_copy = alloca(16);
|
||||
copy_rvalue = 1;
|
||||
}
|
||||
ffi_call_N32(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, rvalue_copy, fn);
|
||||
if (copy_rvalue)
|
||||
memcpy(ecif.rvalue, rvalue_copy, cif->rtype->size);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
@ -490,9 +537,11 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
|
|||
}
|
||||
}
|
||||
|
||||
#if FFI_CLOSURES /* N32 not implemented yet, FFI_CLOSURES not defined */
|
||||
#if FFI_CLOSURES
|
||||
#if defined(FFI_MIPS_O32)
|
||||
extern void ffi_closure_O32(void);
|
||||
#else
|
||||
extern void ffi_closure_N32(void);
|
||||
#endif /* FFI_MIPS_O32 */
|
||||
|
||||
ffi_status
|
||||
|
@ -503,23 +552,58 @@ ffi_prep_closure_loc (ffi_closure *closure,
|
|||
void *codeloc)
|
||||
{
|
||||
unsigned int *tramp = (unsigned int *) &closure->tramp[0];
|
||||
unsigned int fn;
|
||||
unsigned int ctx = (unsigned int) codeloc;
|
||||
void * fn;
|
||||
char *clear_location = (char *) codeloc;
|
||||
|
||||
#if defined(FFI_MIPS_O32)
|
||||
FFI_ASSERT(cif->abi == FFI_O32 || cif->abi == FFI_O32_SOFT_FLOAT);
|
||||
fn = (unsigned int) ffi_closure_O32;
|
||||
fn = ffi_closure_O32;
|
||||
#else /* FFI_MIPS_N32 */
|
||||
FFI_ASSERT(cif->abi == FFI_N32);
|
||||
FFI_ASSERT(!"not implemented");
|
||||
FFI_ASSERT(cif->abi == FFI_N32 || cif->abi == FFI_N64);
|
||||
fn = ffi_closure_N32;
|
||||
#endif /* FFI_MIPS_O32 */
|
||||
|
||||
tramp[0] = 0x3c190000 | (fn >> 16); /* lui $25,high(fn) */
|
||||
tramp[1] = 0x37390000 | (fn & 0xffff); /* ori $25,low(fn) */
|
||||
tramp[2] = 0x3c080000 | (ctx >> 16); /* lui $8,high(ctx) */
|
||||
tramp[3] = 0x03200008; /* jr $25 */
|
||||
tramp[4] = 0x35080000 | (ctx & 0xffff); /* ori $8,low(ctx) */
|
||||
#if defined(FFI_MIPS_O32) || (_MIPS_SIM ==_ABIN32)
|
||||
/* lui $25,high(fn) */
|
||||
tramp[0] = 0x3c190000 | ((unsigned)fn >> 16);
|
||||
/* ori $25,low(fn) */
|
||||
tramp[1] = 0x37390000 | ((unsigned)fn & 0xffff);
|
||||
/* lui $12,high(codeloc) */
|
||||
tramp[2] = 0x3c0c0000 | ((unsigned)codeloc >> 16);
|
||||
/* jr $25 */
|
||||
tramp[3] = 0x03200008;
|
||||
/* ori $12,low(codeloc) */
|
||||
tramp[4] = 0x358c0000 | ((unsigned)codeloc & 0xffff);
|
||||
#else
|
||||
/* N64 has a somewhat larger trampoline. */
|
||||
/* lui $25,high(fn) */
|
||||
tramp[0] = 0x3c190000 | ((unsigned long)fn >> 48);
|
||||
/* lui $12,high(codeloc) */
|
||||
tramp[1] = 0x3c0c0000 | ((unsigned long)codeloc >> 48);
|
||||
/* ori $25,mid-high(fn) */
|
||||
tramp[2] = 0x37390000 | (((unsigned long)fn >> 32 ) & 0xffff);
|
||||
/* ori $12,mid-high(codeloc) */
|
||||
tramp[3] = 0x358c0000 | (((unsigned long)codeloc >> 32) & 0xffff);
|
||||
/* dsll $25,$25,16 */
|
||||
tramp[4] = 0x0019cc38;
|
||||
/* dsll $12,$12,16 */
|
||||
tramp[5] = 0x000c6438;
|
||||
/* ori $25,mid-low(fn) */
|
||||
tramp[6] = 0x37390000 | (((unsigned long)fn >> 16 ) & 0xffff);
|
||||
/* ori $12,mid-low(codeloc) */
|
||||
tramp[7] = 0x358c0000 | (((unsigned long)codeloc >> 16) & 0xffff);
|
||||
/* dsll $25,$25,16 */
|
||||
tramp[8] = 0x0019cc38;
|
||||
/* dsll $12,$12,16 */
|
||||
tramp[9] = 0x000c6438;
|
||||
/* ori $25,low(fn) */
|
||||
tramp[10] = 0x37390000 | ((unsigned long)fn & 0xffff);
|
||||
/* jr $25 */
|
||||
tramp[11] = 0x03200008;
|
||||
/* ori $12,low(codeloc) */
|
||||
tramp[12] = 0x358c0000 | ((unsigned long)codeloc & 0xffff);
|
||||
|
||||
#endif
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
|
@ -567,7 +651,7 @@ ffi_closure_mips_inner_O32 (ffi_closure *closure,
|
|||
|
||||
if ((cif->flags >> (FFI_FLAG_BITS * 2)) == FFI_TYPE_STRUCT)
|
||||
{
|
||||
rvalue = (void *) ar[0];
|
||||
rvalue = (void *)(UINT32)ar[0];
|
||||
argn = 1;
|
||||
}
|
||||
|
||||
|
@ -645,4 +729,177 @@ ffi_closure_mips_inner_O32 (ffi_closure *closure,
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(FFI_MIPS_N32)
|
||||
|
||||
static void
|
||||
copy_struct_N32(char *target, unsigned offset, ffi_abi abi, ffi_type *type,
|
||||
int argn, unsigned arg_offset, ffi_arg *ar,
|
||||
ffi_arg *fpr)
|
||||
{
|
||||
ffi_type **elt_typep = type->elements;
|
||||
while(*elt_typep)
|
||||
{
|
||||
ffi_type *elt_type = *elt_typep;
|
||||
unsigned o;
|
||||
char *tp;
|
||||
char *argp;
|
||||
char *fpp;
|
||||
|
||||
o = ALIGN(offset, elt_type->alignment);
|
||||
arg_offset += o - offset;
|
||||
offset = o;
|
||||
argn += arg_offset / sizeof(ffi_arg);
|
||||
arg_offset = arg_offset % sizeof(ffi_arg);
|
||||
|
||||
argp = (char *)(ar + argn);
|
||||
fpp = (char *)(argn >= 8 ? ar + argn : fpr + argn);
|
||||
|
||||
tp = target + offset;
|
||||
|
||||
if (elt_type->type == FFI_TYPE_DOUBLE)
|
||||
*(double *)tp = *(double *)fpp;
|
||||
else
|
||||
memcpy(tp, argp + arg_offset, elt_type->size);
|
||||
|
||||
offset += elt_type->size;
|
||||
arg_offset += elt_type->size;
|
||||
elt_typep++;
|
||||
argn += arg_offset / sizeof(ffi_arg);
|
||||
arg_offset = arg_offset % sizeof(ffi_arg);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Decodes the arguments to a function, which will be stored on the
|
||||
* stack. AR is the pointer to the beginning of the integer
|
||||
* arguments. FPR is a pointer to the area where floating point
|
||||
* registers have been saved.
|
||||
*
|
||||
* RVALUE is the location where the function return value will be
|
||||
* stored. CLOSURE is the prepared closure to invoke.
|
||||
*
|
||||
* This function should only be called from assembly, which is in
|
||||
* turn called from a trampoline.
|
||||
*
|
||||
* Returns the function return flags.
|
||||
*
|
||||
*/
|
||||
int
|
||||
ffi_closure_mips_inner_N32 (ffi_closure *closure,
|
||||
void *rvalue, ffi_arg *ar,
|
||||
ffi_arg *fpr)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
void **avaluep;
|
||||
ffi_arg *avalue;
|
||||
ffi_type **arg_types;
|
||||
int i, avn, argn;
|
||||
|
||||
cif = closure->cif;
|
||||
avalue = alloca (cif->nargs * sizeof (ffi_arg));
|
||||
avaluep = alloca (cif->nargs * sizeof (ffi_arg));
|
||||
|
||||
argn = 0;
|
||||
|
||||
if (cif->rstruct_flag)
|
||||
{
|
||||
#if _MIPS_SIM==_ABIN32
|
||||
rvalue = (void *)(UINT32)ar[0];
|
||||
#else /* N64 */
|
||||
rvalue = (void *)ar[0];
|
||||
#endif
|
||||
argn = 1;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
avn = cif->nargs;
|
||||
arg_types = cif->arg_types;
|
||||
|
||||
while (i < avn)
|
||||
{
|
||||
if (arg_types[i]->type == FFI_TYPE_FLOAT
|
||||
|| arg_types[i]->type == FFI_TYPE_DOUBLE)
|
||||
{
|
||||
ffi_arg *argp = argn >= 8 ? ar + argn : fpr + argn;
|
||||
#ifdef __MIPSEB__
|
||||
if (arg_types[i]->type == FFI_TYPE_FLOAT && argn < 8)
|
||||
avaluep[i] = ((char *) argp) + sizeof (float);
|
||||
else
|
||||
#endif
|
||||
avaluep[i] = (char *) argp;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned type = arg_types[i]->type;
|
||||
|
||||
if (arg_types[i]->alignment > sizeof(ffi_arg))
|
||||
argn = ALIGN(argn, arg_types[i]->alignment / sizeof(ffi_arg));
|
||||
|
||||
ffi_arg *argp = ar + argn;
|
||||
|
||||
/* The size of a pointer depends on the ABI */
|
||||
if (type == FFI_TYPE_POINTER)
|
||||
type = (cif->abi == FFI_N64) ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
avaluep[i] = &avalue[i];
|
||||
*(SINT8 *) &avalue[i] = (SINT8) *argp;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
avaluep[i] = &avalue[i];
|
||||
*(UINT8 *) &avalue[i] = (UINT8) *argp;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
avaluep[i] = &avalue[i];
|
||||
*(SINT16 *) &avalue[i] = (SINT16) *argp;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
avaluep[i] = &avalue[i];
|
||||
*(UINT16 *) &avalue[i] = (UINT16) *argp;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
avaluep[i] = &avalue[i];
|
||||
*(SINT32 *) &avalue[i] = (SINT32) *argp;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
avaluep[i] = &avalue[i];
|
||||
*(UINT32 *) &avalue[i] = (UINT32) *argp;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
if (argn < 8)
|
||||
{
|
||||
/* Allocate space for the struct as at least part of
|
||||
it was passed in registers. */
|
||||
avaluep[i] = alloca(arg_types[i]->size);
|
||||
copy_struct_N32(avaluep[i], 0, cif->abi, arg_types[i],
|
||||
argn, 0, ar, fpr);
|
||||
|
||||
break;
|
||||
}
|
||||
/* Else fall through. */
|
||||
default:
|
||||
avaluep[i] = (char *) argp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
argn += ALIGN(arg_types[i]->size, sizeof(ffi_arg)) / sizeof(ffi_arg);
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
(closure->fun) (cif, rvalue, avaluep, closure->user_data);
|
||||
|
||||
return cif->flags >> (FFI_FLAG_BITS * 8);
|
||||
}
|
||||
|
||||
#endif /* FFI_MIPS_N32 */
|
||||
|
||||
#endif /* FFI_CLOSURES */
|
||||
|
|
|
@ -104,19 +104,28 @@
|
|||
#define ra $31
|
||||
|
||||
#ifdef FFI_MIPS_O32
|
||||
#define REG_L lw
|
||||
#define REG_S sw
|
||||
#define SUBU subu
|
||||
#define ADDU addu
|
||||
#define SRL srl
|
||||
#define LI li
|
||||
# define REG_L lw
|
||||
# define REG_S sw
|
||||
# define SUBU subu
|
||||
# define ADDU addu
|
||||
# define SRL srl
|
||||
# define LI li
|
||||
#else /* !FFI_MIPS_O32 */
|
||||
#define REG_L ld
|
||||
#define REG_S sd
|
||||
#define SUBU dsubu
|
||||
#define ADDU daddu
|
||||
#define SRL dsrl
|
||||
#define LI dli
|
||||
# define REG_L ld
|
||||
# define REG_S sd
|
||||
# define SUBU dsubu
|
||||
# define ADDU daddu
|
||||
# define SRL dsrl
|
||||
# define LI dli
|
||||
# if (_MIPS_SIM==_ABI64)
|
||||
# define LA dla
|
||||
# define EH_FRAME_ALIGN 3
|
||||
# define FDE_ADDR_BYTES .8byte
|
||||
# else
|
||||
# define LA la
|
||||
# define EH_FRAME_ALIGN 2
|
||||
# define FDE_ADDR_BYTES .4byte
|
||||
# endif /* _MIPS_SIM==_ABI64 */
|
||||
#endif /* !FFI_MIPS_O32 */
|
||||
#else /* !LIBFFI_ASM */
|
||||
#ifdef FFI_MIPS_O32
|
||||
|
@ -143,7 +152,11 @@ typedef enum ffi_abi {
|
|||
FFI_DEFAULT_ABI = FFI_O32,
|
||||
#endif
|
||||
#else
|
||||
# if _MIPS_SIM==_ABI64
|
||||
FFI_DEFAULT_ABI = FFI_N64,
|
||||
# else
|
||||
FFI_DEFAULT_ABI = FFI_N32,
|
||||
# endif
|
||||
#endif
|
||||
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
|
@ -158,8 +171,13 @@ typedef enum ffi_abi {
|
|||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 20
|
||||
#else
|
||||
/* N32/N64 not implemented yet. */
|
||||
#define FFI_CLOSURES 0
|
||||
/* N32/N64. */
|
||||
# define FFI_CLOSURES 1
|
||||
#if _MIPS_SIM==_ABI64
|
||||
#define FFI_TRAMPOLINE_SIZE 52
|
||||
#else
|
||||
#define FFI_TRAMPOLINE_SIZE 20
|
||||
#endif
|
||||
#endif /* FFI_MIPS_O32 */
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
|
|
|
@ -45,13 +45,19 @@
|
|||
.globl ffi_call_N32
|
||||
.ent ffi_call_N32
|
||||
ffi_call_N32:
|
||||
.LFB3:
|
||||
.frame $fp, SIZEOF_FRAME, ra
|
||||
.mask 0xc0000000,-FFI_SIZEOF_ARG
|
||||
.fmask 0x00000000,0
|
||||
|
||||
# Prologue
|
||||
SUBU $sp, SIZEOF_FRAME # Frame size
|
||||
.LCFI0:
|
||||
REG_S $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Save frame pointer
|
||||
REG_S ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp) # Save return address
|
||||
.LCFI1:
|
||||
move $fp, $sp
|
||||
|
||||
.LCFI3:
|
||||
move t9, callback # callback function pointer
|
||||
REG_S bytes, 2*FFI_SIZEOF_ARG($fp) # bytes
|
||||
REG_S flags, 3*FFI_SIZEOF_ARG($fp) # flags
|
||||
|
@ -315,6 +321,224 @@ epilogue:
|
|||
ADDU $sp, SIZEOF_FRAME # Fix stack pointer
|
||||
j ra
|
||||
|
||||
.LFE3:
|
||||
.end ffi_call_N32
|
||||
|
||||
/* ffi_closure_N32. Expects address of the passed-in ffi_closure in t0
|
||||
($12). Stores any arguments passed in registers onto the stack,
|
||||
then calls ffi_closure_mips_inner_N32, which then decodes
|
||||
them.
|
||||
|
||||
Stack layout:
|
||||
|
||||
20 - Start of parameters, original sp
|
||||
19 - Called function a7 save
|
||||
18 - Called function a6 save
|
||||
17 - Called function a5 save
|
||||
16 - Called function a4 save
|
||||
15 - Called function a3 save
|
||||
14 - Called function a2 save
|
||||
13 - Called function a1 save
|
||||
12 - Called function a0 save
|
||||
11 - Called function f19
|
||||
10 - Called function f18
|
||||
9 - Called function f17
|
||||
8 - Called function f16
|
||||
7 - Called function f15
|
||||
6 - Called function f14
|
||||
5 - Called function f13
|
||||
4 - Called function f12
|
||||
3 - return value high (v1 or $f2)
|
||||
2 - return value low (v0 or $f0)
|
||||
1 - ra save
|
||||
0 - gp save our sp points here
|
||||
*/
|
||||
|
||||
#define SIZEOF_FRAME2 (20 * FFI_SIZEOF_ARG)
|
||||
|
||||
#define A7_OFF2 (19 * FFI_SIZEOF_ARG)
|
||||
#define A6_OFF2 (18 * FFI_SIZEOF_ARG)
|
||||
#define A5_OFF2 (17 * FFI_SIZEOF_ARG)
|
||||
#define A4_OFF2 (16 * FFI_SIZEOF_ARG)
|
||||
#define A3_OFF2 (15 * FFI_SIZEOF_ARG)
|
||||
#define A2_OFF2 (14 * FFI_SIZEOF_ARG)
|
||||
#define A1_OFF2 (13 * FFI_SIZEOF_ARG)
|
||||
#define A0_OFF2 (12 * FFI_SIZEOF_ARG)
|
||||
|
||||
#define F19_OFF2 (11 * FFI_SIZEOF_ARG)
|
||||
#define F18_OFF2 (10 * FFI_SIZEOF_ARG)
|
||||
#define F17_OFF2 (9 * FFI_SIZEOF_ARG)
|
||||
#define F16_OFF2 (8 * FFI_SIZEOF_ARG)
|
||||
#define F15_OFF2 (7 * FFI_SIZEOF_ARG)
|
||||
#define F14_OFF2 (6 * FFI_SIZEOF_ARG)
|
||||
#define F13_OFF2 (5 * FFI_SIZEOF_ARG)
|
||||
#define F12_OFF2 (4 * FFI_SIZEOF_ARG)
|
||||
|
||||
#define V1_OFF2 (3 * FFI_SIZEOF_ARG)
|
||||
#define V0_OFF2 (2 * FFI_SIZEOF_ARG)
|
||||
|
||||
#define RA_OFF2 (1 * FFI_SIZEOF_ARG)
|
||||
#define GP_OFF2 (0 * FFI_SIZEOF_ARG)
|
||||
|
||||
.align 2
|
||||
.globl ffi_closure_N32
|
||||
.ent ffi_closure_N32
|
||||
ffi_closure_N32:
|
||||
.LFB2:
|
||||
.frame $sp, SIZEOF_FRAME2, ra
|
||||
.mask 0x90000000,-(SIZEOF_FRAME2 - RA_OFF2)
|
||||
.fmask 0x00000000,0
|
||||
SUBU $sp, SIZEOF_FRAME2
|
||||
.LCFI5:
|
||||
.cpsetup t9, GP_OFF2, ffi_closure_N32
|
||||
REG_S ra, RA_OFF2($sp) # Save return address
|
||||
.LCFI6:
|
||||
# Store all possible argument registers. If there are more than
|
||||
# fit in registers, then they were stored on the stack.
|
||||
REG_S a0, A0_OFF2($sp)
|
||||
REG_S a1, A1_OFF2($sp)
|
||||
REG_S a2, A2_OFF2($sp)
|
||||
REG_S a3, A3_OFF2($sp)
|
||||
REG_S a4, A4_OFF2($sp)
|
||||
REG_S a5, A5_OFF2($sp)
|
||||
REG_S a6, A6_OFF2($sp)
|
||||
REG_S a7, A7_OFF2($sp)
|
||||
|
||||
# Store all possible float/double registers.
|
||||
s.d $f12, F12_OFF2($sp)
|
||||
s.d $f13, F13_OFF2($sp)
|
||||
s.d $f14, F14_OFF2($sp)
|
||||
s.d $f15, F15_OFF2($sp)
|
||||
s.d $f16, F16_OFF2($sp)
|
||||
s.d $f17, F17_OFF2($sp)
|
||||
s.d $f18, F18_OFF2($sp)
|
||||
s.d $f19, F19_OFF2($sp)
|
||||
|
||||
# Call ffi_closure_mips_inner_N32 to do the real work.
|
||||
LA t9, ffi_closure_mips_inner_N32
|
||||
move a0, $12 # Pointer to the ffi_closure
|
||||
addu a1, $sp, V0_OFF2
|
||||
addu a2, $sp, A0_OFF2
|
||||
addu a3, $sp, F12_OFF2
|
||||
jalr t9
|
||||
|
||||
# Return flags are in v0
|
||||
bne v0, FFI_TYPE_INT, cls_retfloat
|
||||
REG_L v0, V0_OFF2($sp)
|
||||
b cls_epilogue
|
||||
|
||||
cls_retfloat:
|
||||
bne v0, FFI_TYPE_FLOAT, cls_retdouble
|
||||
l.s $f0, V0_OFF2($sp)
|
||||
b cls_epilogue
|
||||
|
||||
cls_retdouble:
|
||||
bne v0, FFI_TYPE_DOUBLE, cls_retstruct_d
|
||||
l.d $f0, V0_OFF2($sp)
|
||||
b cls_epilogue
|
||||
|
||||
cls_retstruct_d:
|
||||
bne v0, FFI_TYPE_STRUCT_D, cls_retstruct_f
|
||||
l.d $f0, V0_OFF2($sp)
|
||||
b cls_epilogue
|
||||
|
||||
cls_retstruct_f:
|
||||
bne v0, FFI_TYPE_STRUCT_F, cls_retstruct_d_d
|
||||
l.s $f0, V0_OFF2($sp)
|
||||
b cls_epilogue
|
||||
|
||||
cls_retstruct_d_d:
|
||||
bne v0, FFI_TYPE_STRUCT_DD, cls_retstruct_f_f
|
||||
l.d $f0, V0_OFF2($sp)
|
||||
l.d $f2, V1_OFF2($sp)
|
||||
b cls_epilogue
|
||||
|
||||
cls_retstruct_f_f:
|
||||
bne v0, FFI_TYPE_STRUCT_FF, cls_retstruct_d_f
|
||||
l.s $f0, V0_OFF2($sp)
|
||||
l.s $f2, V1_OFF2($sp)
|
||||
b cls_epilogue
|
||||
|
||||
cls_retstruct_d_f:
|
||||
bne v0, FFI_TYPE_STRUCT_DF, cls_retstruct_f_d
|
||||
l.d $f0, V0_OFF2($sp)
|
||||
l.s $f2, V1_OFF2($sp)
|
||||
b cls_epilogue
|
||||
|
||||
cls_retstruct_f_d:
|
||||
bne v0, FFI_TYPE_STRUCT_FD, cls_retstruct_small2
|
||||
l.s $f0, V0_OFF2($sp)
|
||||
l.d $f2, V1_OFF2($sp)
|
||||
b cls_epilogue
|
||||
|
||||
cls_retstruct_small2:
|
||||
REG_L v0, V0_OFF2($sp)
|
||||
REG_L v1, V1_OFF2($sp)
|
||||
|
||||
# Epilogue
|
||||
cls_epilogue:
|
||||
REG_L ra, RA_OFF2($sp) # Restore return address
|
||||
.cpreturn
|
||||
ADDU $sp, SIZEOF_FRAME2
|
||||
j ra
|
||||
.LFE2:
|
||||
.end ffi_closure_N32
|
||||
|
||||
.section .eh_frame,"aw",@progbits
|
||||
.Lframe1:
|
||||
.4byte .LECIE1-.LSCIE1 # length
|
||||
.LSCIE1:
|
||||
.4byte 0x0 # CIE
|
||||
.byte 0x1 # Version 1
|
||||
.ascii "\000" # Augmentation
|
||||
.uleb128 0x1 # Code alignment 1
|
||||
.sleb128 -4 # Data alignment -4
|
||||
.byte 0x1f # Return Address $31
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1d # in $sp
|
||||
.uleb128 0x0 # offset 0
|
||||
.align EH_FRAME_ALIGN
|
||||
.LECIE1:
|
||||
|
||||
.LSFDE1:
|
||||
.4byte .LEFDE1-.LASFDE1 # length.
|
||||
.LASFDE1:
|
||||
.4byte .LASFDE1-.Lframe1 # CIE_pointer.
|
||||
FDE_ADDR_BYTES .LFB3 # initial_location.
|
||||
FDE_ADDR_BYTES .LFE3-.LFB3 # address_range.
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI0-.LFB3 # to .LCFI0
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 SIZEOF_FRAME # adjust stack.by SIZEOF_FRAME
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI1-.LCFI0 # to .LCFI1
|
||||
.byte 0x9e # DW_CFA_offset of $fp
|
||||
.uleb128 2*FFI_SIZEOF_ARG/4 #
|
||||
.byte 0x9f # DW_CFA_offset of ra
|
||||
.uleb128 1*FFI_SIZEOF_ARG/4 #
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI3-.LCFI1 # to .LCFI3
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.uleb128 0x1e # in $fp
|
||||
.align EH_FRAME_ALIGN
|
||||
.LEFDE1:
|
||||
.LSFDE3:
|
||||
.4byte .LEFDE3-.LASFDE3 # length
|
||||
.LASFDE3:
|
||||
.4byte .LASFDE3-.Lframe1 # CIE_pointer.
|
||||
FDE_ADDR_BYTES .LFB2 # initial_location.
|
||||
FDE_ADDR_BYTES .LFE2-.LFB2 # address_range.
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI5-.LFB2 # to .LCFI5
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 SIZEOF_FRAME2 # adjust stack.by SIZEOF_FRAME
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI6-.LCFI5 # to .LCFI6
|
||||
.byte 0x9c # DW_CFA_offset of $gp ($28)
|
||||
.uleb128 (SIZEOF_FRAME2 - GP_OFF2)/4
|
||||
.byte 0x9f # DW_CFA_offset of ra ($31)
|
||||
.uleb128 (SIZEOF_FRAME2 - RA_OFF2)/4
|
||||
.align EH_FRAME_ALIGN
|
||||
.LEFDE3:
|
||||
|
||||
#endif
|
||||
|
|
|
@ -183,27 +183,30 @@ $LFE0:
|
|||
|
||||
|
||||
/* ffi_closure_O32. Expects address of the passed-in ffi_closure
|
||||
in t0. Stores any arguments passed in registers onto the
|
||||
in t4 ($12). Stores any arguments passed in registers onto the
|
||||
stack, then calls ffi_closure_mips_inner_O32, which
|
||||
then decodes them.
|
||||
|
||||
Stack layout:
|
||||
|
||||
14 - Start of parameters, original sp
|
||||
13 - ra save
|
||||
12 - fp save
|
||||
11 - $16 (s0) save
|
||||
10 - cprestore
|
||||
9 - return value high (v1)
|
||||
8 - return value low (v0)
|
||||
7 - f14 (le high, be low)
|
||||
6 - f14 (le low, be high)
|
||||
5 - f12 (le high, be low)
|
||||
4 - f12 (le low, be high)
|
||||
3 - Called function a3 save
|
||||
2 - Called function a2 save
|
||||
1 - Called function a1 save
|
||||
0 - Called function a0 save our sp, fp point here
|
||||
3 - a3 save
|
||||
2 - a2 save
|
||||
1 - a1 save
|
||||
0 - a0 save, original sp
|
||||
-1 - ra save
|
||||
-2 - fp save
|
||||
-3 - $16 (s0) save
|
||||
-4 - cprestore
|
||||
-5 - return value high (v1)
|
||||
-6 - return value low (v0)
|
||||
-7 - f14 (le high, be low)
|
||||
-8 - f14 (le low, be high)
|
||||
-9 - f12 (le high, be low)
|
||||
-10 - f12 (le low, be high)
|
||||
-11 - Called function a3 save
|
||||
-12 - Called function a2 save
|
||||
-13 - Called function a1 save
|
||||
-14 - Called function a0 save, our sp and fp point here
|
||||
*/
|
||||
|
||||
#define SIZEOF_FRAME2 (14 * FFI_SIZEOF_ARG)
|
||||
|
@ -251,7 +254,7 @@ $LCFI7:
|
|||
REG_S a3, A3_OFF2($fp)
|
||||
|
||||
# Load ABI enum to s0
|
||||
REG_L $16, 20($8) # cif pointer follows tramp.
|
||||
REG_L $16, 20($12) # cif pointer follows tramp.
|
||||
REG_L $16, 0($16) # abi is first member.
|
||||
|
||||
li $13, 1 # FFI_O32
|
||||
|
@ -263,7 +266,7 @@ $LCFI7:
|
|||
1:
|
||||
# Call ffi_closure_mips_inner_O32 to do the work.
|
||||
la t9, ffi_closure_mips_inner_O32
|
||||
move a0, $8 # Pointer to the ffi_closure
|
||||
move a0, $12 # Pointer to the ffi_closure
|
||||
addu a1, $fp, V0_OFF2
|
||||
addu a2, $fp, A0_OFF2
|
||||
addu a3, $fp, FA_0_0_OFF2
|
||||
|
|
Loading…
Add table
Reference in a new issue