mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-27 05:44:15 +08:00
configure.in (powerpc64*-*-linux*): Remove.
* configure.in (powerpc64*-*-linux*): Remove. * configure: Rebuilt. libffi/ * include/ffi.h.in (POWERPC64): Define if 64-bit. (enum ffi_abi): Add FFI_LINUX64 on POWERPC. Make it the default on POWERPC64. (FFI_TRAMPOLINE_SIZE): Define to 24 on POWERPC64. * configure.in: Change powerpc-*-linux* into powerpc*-*-linux*. * configure: Rebuilt. * src/powerpc/ffi.c (hidden): Define. (ffi_prep_args_SYSV): Renamed from ffi_prep_args. Cast pointers to unsigned long to shut up warnings. (NUM_GPR_ARG_REGISTERS64, NUM_FPR_ARG_REGISTERS64, ASM_NEEDS_REGISTERS64): New. (ffi_prep_args64): New function. (ffi_prep_cif_machdep): Handle FFI_LINUX64 ABI. (ffi_call): Likewise. (ffi_prep_closure): Likewise. (flush_icache): Surround by #ifndef POWERPC64. (ffi_dblfl): New union type. (ffi_closure_helper_SYSV): Use it to avoid aliasing problems. (ffi_closure_helper_LINUX64): New function. * src/powerpc/ppc_closure.S: Surround whole file by #ifndef __powerpc64__. * src/powerpc/sysv.S: Likewise. (ffi_call_SYSV): Rename ffi_prep_args to ffi_prep_args_SYSV. * src/powerpc/linux64.S: New file. * src/powerpc/linux64_closure.S: New file. * Makefile.am (EXTRA_DIST): Add src/powerpc/linux64.S and src/powerpc/linux64_closure.S. (TARGET_SRC_POWERPC): Likewise. * src/ffitest.c (closure_test_fn, closure_test_fn1, closure_test_fn2, closure_test_fn3): Fix result printing on big-endian 64-bit machines. (main): Print tst2_arg instead of uninitialized tst2_result. * src/ffitest.c (main): Hide what closure pointer really points to from the compiler. From-SVN: r65781
This commit is contained in:
parent
9c59483708
commit
e9b841813c
@ -1,3 +1,8 @@
|
||||
2003-04-18 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* configure.in (powerpc64*-*-linux*): Remove.
|
||||
* configure: Rebuilt.
|
||||
|
||||
2003-04-17 Phil Edwards <pme@gcc.gnu.org>
|
||||
|
||||
* Makefile.tpl (GCC_STRAP_TARGETS): New variable containing all the
|
||||
|
5
configure
vendored
5
configure
vendored
@ -1267,11 +1267,6 @@ case "${target}" in
|
||||
powerpc-*-eabi)
|
||||
noconfigdirs="$noconfigdirs ${libgcj}"
|
||||
;;
|
||||
powerpc64*-*-linux*)
|
||||
noconfigdirs="$noconfigdirs target-newlib target-libgloss"
|
||||
# not yet ported.
|
||||
noconfigdirs="$noconfigdirs target-libffi"
|
||||
;;
|
||||
rs6000-*-lynxos*)
|
||||
noconfigdirs="$noconfigdirs target-newlib gprof ${libgcj}"
|
||||
;;
|
||||
|
@ -607,11 +607,6 @@ case "${target}" in
|
||||
powerpc-*-eabi)
|
||||
noconfigdirs="$noconfigdirs ${libgcj}"
|
||||
;;
|
||||
powerpc64*-*-linux*)
|
||||
noconfigdirs="$noconfigdirs target-newlib target-libgloss"
|
||||
# not yet ported.
|
||||
noconfigdirs="$noconfigdirs target-libffi"
|
||||
;;
|
||||
rs6000-*-lynxos*)
|
||||
noconfigdirs="$noconfigdirs target-newlib gprof ${libgcj}"
|
||||
;;
|
||||
|
@ -1,3 +1,42 @@
|
||||
2003-04-18 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* include/ffi.h.in (POWERPC64): Define if 64-bit.
|
||||
(enum ffi_abi): Add FFI_LINUX64 on POWERPC.
|
||||
Make it the default on POWERPC64.
|
||||
(FFI_TRAMPOLINE_SIZE): Define to 24 on POWERPC64.
|
||||
* configure.in: Change powerpc-*-linux* into powerpc*-*-linux*.
|
||||
* configure: Rebuilt.
|
||||
* src/powerpc/ffi.c (hidden): Define.
|
||||
(ffi_prep_args_SYSV): Renamed from
|
||||
ffi_prep_args. Cast pointers to unsigned long to shut up warnings.
|
||||
(NUM_GPR_ARG_REGISTERS64, NUM_FPR_ARG_REGISTERS64,
|
||||
ASM_NEEDS_REGISTERS64): New.
|
||||
(ffi_prep_args64): New function.
|
||||
(ffi_prep_cif_machdep): Handle FFI_LINUX64 ABI.
|
||||
(ffi_call): Likewise.
|
||||
(ffi_prep_closure): Likewise.
|
||||
(flush_icache): Surround by #ifndef POWERPC64.
|
||||
(ffi_dblfl): New union type.
|
||||
(ffi_closure_helper_SYSV): Use it to avoid aliasing problems.
|
||||
(ffi_closure_helper_LINUX64): New function.
|
||||
* src/powerpc/ppc_closure.S: Surround whole file by #ifndef
|
||||
__powerpc64__.
|
||||
* src/powerpc/sysv.S: Likewise.
|
||||
(ffi_call_SYSV): Rename ffi_prep_args to ffi_prep_args_SYSV.
|
||||
* src/powerpc/linux64.S: New file.
|
||||
* src/powerpc/linux64_closure.S: New file.
|
||||
* Makefile.am (EXTRA_DIST): Add src/powerpc/linux64.S and
|
||||
src/powerpc/linux64_closure.S.
|
||||
(TARGET_SRC_POWERPC): Likewise.
|
||||
|
||||
* src/ffitest.c (closure_test_fn, closure_test_fn1, closure_test_fn2,
|
||||
closure_test_fn3): Fix result printing on big-endian 64-bit
|
||||
machines.
|
||||
(main): Print tst2_arg instead of uninitialized tst2_result.
|
||||
|
||||
* src/ffitest.c (main): Hide what closure pointer really points to
|
||||
from the compiler.
|
||||
|
||||
2003-04-16 Richard Earnshaw <rearnsha@arm.com>
|
||||
|
||||
* configure.in (arm-*-netbsdelf*): Add configuration.
|
||||
|
@ -12,6 +12,7 @@ EXTRA_DIST = LICENSE ChangeLog.v1 src/mips/ffi.c src/mips/n32.S \
|
||||
src/alpha/ffi.c src/alpha/osf.S \
|
||||
src/m68k/ffi.c src/m68k/sysv.S \
|
||||
src/powerpc/ffi.c src/powerpc/sysv.S \
|
||||
src/powerpc/linux64.S src/powerpc/linux64_closure.S \
|
||||
src/powerpc/ppc_closure.S src/powerpc/asm.h \
|
||||
src/powerpc/ffi_darwin.c \
|
||||
src/powerpc/darwin.S src/powerpc/aix.S \
|
||||
@ -94,7 +95,7 @@ TARGET_SRC_SPARC = src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S
|
||||
TARGET_SRC_ALPHA = src/alpha/ffi.c src/alpha/osf.S
|
||||
TARGET_SRC_IA64 = src/ia64/ffi.c src/ia64/unix.S
|
||||
TARGET_SRC_M68K = src/m68k/ffi.c src/m68k/sysv.S
|
||||
TARGET_SRC_POWERPC = src/powerpc/ffi.c src/powerpc/sysv.S src/powerpc/ppc_closure.S
|
||||
TARGET_SRC_POWERPC = src/powerpc/ffi.c src/powerpc/sysv.S src/powerpc/ppc_closure.S src/powerpc/linux64.S src/powerpc/linux64_closure.S
|
||||
TARGET_SRC_POWERPC_AIX = src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/aix_closure.S
|
||||
TARGET_SRC_POWERPC_DARWIN = src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S
|
||||
TARGET_SRC_ARM = src/arm/sysv.S src/arm/ffi.c
|
||||
|
@ -95,6 +95,7 @@ EXTRA_DIST = LICENSE ChangeLog.v1 src/mips/ffi.c src/mips/n32.S \
|
||||
src/alpha/ffi.c src/alpha/osf.S \
|
||||
src/m68k/ffi.c src/m68k/sysv.S \
|
||||
src/powerpc/ffi.c src/powerpc/sysv.S \
|
||||
src/powerpc/linux64.S src/powerpc/linux64_closure.S \
|
||||
src/powerpc/ppc_closure.S src/powerpc/asm.h \
|
||||
src/powerpc/ffi_darwin.c \
|
||||
src/powerpc/darwin.S src/powerpc/aix.S \
|
||||
@ -173,7 +174,7 @@ TARGET_SRC_SPARC = src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S
|
||||
TARGET_SRC_ALPHA = src/alpha/ffi.c src/alpha/osf.S
|
||||
TARGET_SRC_IA64 = src/ia64/ffi.c src/ia64/unix.S
|
||||
TARGET_SRC_M68K = src/m68k/ffi.c src/m68k/sysv.S
|
||||
TARGET_SRC_POWERPC = src/powerpc/ffi.c src/powerpc/sysv.S src/powerpc/ppc_closure.S
|
||||
TARGET_SRC_POWERPC = src/powerpc/ffi.c src/powerpc/sysv.S src/powerpc/ppc_closure.S src/powerpc/linux64.S src/powerpc/linux64_closure.S
|
||||
TARGET_SRC_POWERPC_AIX = src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/aix_closure.S
|
||||
TARGET_SRC_POWERPC_DARWIN = src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S
|
||||
TARGET_SRC_ARM = src/arm/sysv.S src/arm/ffi.c
|
||||
@ -257,7 +258,8 @@ libffi_convenience_la_LIBADD =
|
||||
@POWERPC_TRUE@libffi_convenience_la_OBJECTS = src/debug.lo \
|
||||
@POWERPC_TRUE@src/prep_cif.lo src/types.lo src/raw_api.lo \
|
||||
@POWERPC_TRUE@src/java_raw_api.lo src/powerpc/ffi.lo \
|
||||
@POWERPC_TRUE@src/powerpc/sysv.lo src/powerpc/ppc_closure.lo
|
||||
@POWERPC_TRUE@src/powerpc/sysv.lo src/powerpc/ppc_closure.lo \
|
||||
@POWERPC_TRUE@src/powerpc/linux64.lo src/powerpc/linux64_closure.lo
|
||||
@MIPS_LINUX_TRUE@libffi_convenience_la_OBJECTS = src/debug.lo \
|
||||
@MIPS_LINUX_TRUE@src/prep_cif.lo src/types.lo src/raw_api.lo \
|
||||
@MIPS_LINUX_TRUE@src/java_raw_api.lo src/mips/ffi.lo src/mips/o32.lo
|
||||
@ -301,7 +303,8 @@ libffi_la_LIBADD =
|
||||
@POWERPC_TRUE@libffi_la_OBJECTS = src/debug.lo src/prep_cif.lo \
|
||||
@POWERPC_TRUE@src/types.lo src/raw_api.lo src/java_raw_api.lo \
|
||||
@POWERPC_TRUE@src/powerpc/ffi.lo src/powerpc/sysv.lo \
|
||||
@POWERPC_TRUE@src/powerpc/ppc_closure.lo
|
||||
@POWERPC_TRUE@src/powerpc/ppc_closure.lo src/powerpc/linux64.lo \
|
||||
@POWERPC_TRUE@src/powerpc/linux64_closure.lo
|
||||
@MIPS_LINUX_TRUE@libffi_la_OBJECTS = src/debug.lo src/prep_cif.lo \
|
||||
@MIPS_LINUX_TRUE@src/types.lo src/raw_api.lo src/java_raw_api.lo \
|
||||
@MIPS_LINUX_TRUE@src/mips/ffi.lo src/mips/o32.lo
|
||||
|
2
libffi/configure
vendored
2
libffi/configure
vendored
@ -2469,7 +2469,7 @@ ia64*-*-*) TARGET=IA64; TARGETDIR=ia64;;
|
||||
m68k-*-linux*) TARGET=M68K; TARGETDIR=m68k;;
|
||||
mips64*-*);;
|
||||
mips*-*-linux*) TARGET=MIPS_LINUX; TARGETDIR=mips;;
|
||||
powerpc-*-linux* | powerpc-*-sysv*) TARGET=POWERPC; TARGETDIR=powerpc;;
|
||||
powerpc*-*-linux* | powerpc-*-sysv*) TARGET=POWERPC; TARGETDIR=powerpc;;
|
||||
powerpc-*-beos*) TARGET=POWERPC; TARGETDIR=powerpc;;
|
||||
powerpc-*-darwin*) TARGET=POWERPC_DARWIN; TARGETDIR=powerpc;;
|
||||
powerpc-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
|
||||
|
@ -64,7 +64,7 @@ ia64*-*-*) TARGET=IA64; TARGETDIR=ia64;;
|
||||
m68k-*-linux*) TARGET=M68K; TARGETDIR=m68k;;
|
||||
mips64*-*);;
|
||||
mips*-*-linux*) TARGET=MIPS_LINUX; TARGETDIR=mips;;
|
||||
powerpc-*-linux* | powerpc-*-sysv*) TARGET=POWERPC; TARGETDIR=powerpc;;
|
||||
powerpc*-*-linux* | powerpc-*-sysv*) TARGET=POWERPC; TARGETDIR=powerpc;;
|
||||
powerpc-*-beos*) TARGET=POWERPC; TARGETDIR=powerpc;;
|
||||
powerpc-*-darwin*) TARGET=POWERPC_DARWIN; TARGETDIR=powerpc;;
|
||||
powerpc-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
|
||||
|
@ -158,6 +158,12 @@ extern "C" {
|
||||
#define SIZEOF_ARG SIZEOF_VOID_P
|
||||
#endif
|
||||
|
||||
#ifdef POWERPC
|
||||
#if defined (__powerpc64__)
|
||||
#define POWERPC64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SPARC
|
||||
#if defined(__arch64__) || defined(__sparcv9)
|
||||
#define SPARC64
|
||||
@ -250,7 +256,12 @@ typedef enum ffi_abi {
|
||||
#ifdef POWERPC
|
||||
FFI_SYSV,
|
||||
FFI_GCC_SYSV,
|
||||
FFI_LINUX64,
|
||||
# ifdef POWERPC64
|
||||
FFI_DEFAULT_ABI = FFI_LINUX64,
|
||||
# else
|
||||
FFI_DEFAULT_ABI = FFI_GCC_SYSV,
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef POWERPC_AIX
|
||||
@ -435,7 +446,11 @@ struct ffi_ia64_trampoline_struct {
|
||||
#elif defined(POWERPC)
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#ifdef POWERPC64
|
||||
#define FFI_TRAMPOLINE_SIZE 24
|
||||
#else
|
||||
#define FFI_TRAMPOLINE_SIZE 40
|
||||
#endif
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#elif defined(POWERPC_DARWIN)
|
||||
|
@ -309,7 +309,7 @@ closure_test_fn(ffi_cif* cif,void* resp,void** args, void* userdata)
|
||||
(int)(*(int *)args[10]), (int)(*(float *)args[11]),
|
||||
(int)*(int *)args[12], (int)(*(int *)args[13]),
|
||||
(int)(*(int *)args[14]),*(int *)args[15],
|
||||
(int)(long)userdata, *(int*)resp);
|
||||
(int)(long)userdata, (int)*(ffi_arg *)resp);
|
||||
}
|
||||
|
||||
typedef int (*closure_test_type)(unsigned long long, int, unsigned long long,
|
||||
@ -339,7 +339,7 @@ static void closure_test_fn1(ffi_cif* cif,void* resp,void** args,
|
||||
(int)(*(int *)args[10]), (int)(*(float *)args[11]),
|
||||
(int)*(int *)args[12], (int)(*(int *)args[13]),
|
||||
(int)(*(int *)args[14]), *(int *)args[15],
|
||||
(int)(long)userdata, *(int*)resp);
|
||||
(int)(long)userdata, (int)*(ffi_arg *)resp);
|
||||
}
|
||||
|
||||
typedef int (*closure_test_type1)(float, float, float, float, signed short,
|
||||
@ -368,7 +368,7 @@ static void closure_test_fn2(ffi_cif* cif,void* resp,void** args,
|
||||
(int)(*(int *)args[10]), (int)(*(float *)args[11]),
|
||||
(int)*(int *)args[12], (int)(*(float *)args[13]),
|
||||
(int)(*(int *)args[14]), *(int *)args[15], (int)(long)userdata,
|
||||
*(int*)resp);
|
||||
(int)*(ffi_arg *)resp);
|
||||
}
|
||||
|
||||
typedef int (*closure_test_type2)(double, double, double, double, signed short,
|
||||
@ -397,7 +397,7 @@ static void closure_test_fn3(ffi_cif* cif,void* resp,void** args,
|
||||
(int)(*(float *)args[10]), (int)(*(float *)args[11]),
|
||||
(int)*(int *)args[12], (int)(*(float *)args[13]),
|
||||
(int)(*(float *)args[14]), *(int *)args[15], (int)(long)userdata,
|
||||
*(int*)resp);
|
||||
(int)*(ffi_arg *)resp);
|
||||
}
|
||||
|
||||
typedef int (*closure_test_type3)(float, float, float, float, float, float,
|
||||
@ -430,6 +430,7 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
|
||||
/* The closure must not be an automatic variable on
|
||||
platforms (Solaris) that forbid stack execution by default. */
|
||||
static ffi_closure cl;
|
||||
ffi_closure *pcl = &cl;
|
||||
#endif
|
||||
|
||||
ffi_type * cl_arg_types[17];
|
||||
@ -841,8 +842,8 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
|
||||
ts2_arg.d1 = 5.55;
|
||||
ts2_arg.d2 = 6.66;
|
||||
|
||||
printf ("%g\n", ts2_result->d1);
|
||||
printf ("%g\n", ts2_result->d2);
|
||||
printf ("%g\n", ts2_arg.d1);
|
||||
printf ("%g\n", ts2_arg.d2);
|
||||
|
||||
ffi_call(&cif, FFI_FN(struct2), ts2_result, values);
|
||||
|
||||
@ -1161,6 +1162,13 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
|
||||
#endif /* X86_WIN32 */
|
||||
|
||||
# if FFI_CLOSURES
|
||||
# if __GNUC__ >= 2
|
||||
/* Hide before the compiler that pcl is &cl, since on
|
||||
some architectures it is not possible to call a data
|
||||
object using direct function call. */
|
||||
asm ("" : "=g" (pcl) : "0" (pcl));
|
||||
# endif
|
||||
|
||||
/* A simple closure test */
|
||||
{
|
||||
(void) puts("\nEnter FFI_CLOSURES\n");
|
||||
@ -1187,10 +1195,10 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
|
||||
&ffi_type_sint, cl_arg_types) == FFI_OK);
|
||||
|
||||
CHECK(ffi_prep_closure(&cl, &cif, closure_test_fn,
|
||||
CHECK(ffi_prep_closure(pcl, &cif, closure_test_fn,
|
||||
(void *) 3 /* userdata */) == FFI_OK);
|
||||
|
||||
CHECK((*((closure_test_type)(&cl)))
|
||||
CHECK((*((closure_test_type)pcl))
|
||||
(1LL, 2, 3LL, 4, 127, 429LL, 7, 8, 9.5, 10, 11, 12, 13,
|
||||
19, 21, 1) == 680);
|
||||
}
|
||||
@ -1219,10 +1227,10 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
|
||||
&ffi_type_sint, cl_arg_types) == FFI_OK);
|
||||
|
||||
CHECK(ffi_prep_closure(&cl, &cif, closure_test_fn1,
|
||||
CHECK(ffi_prep_closure(pcl, &cif, closure_test_fn1,
|
||||
(void *) 3 /* userdata */) == FFI_OK);
|
||||
|
||||
CHECK((*((closure_test_type1)(&cl)))
|
||||
CHECK((*((closure_test_type1)pcl))
|
||||
(1.1, 2.2, 3.3, 4.4, 127, 5.5, 6.6, 8, 9, 10, 11, 12.0, 13,
|
||||
19, 21, 1) == 255);
|
||||
}
|
||||
@ -1251,10 +1259,10 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
|
||||
&ffi_type_sint, cl_arg_types) == FFI_OK);
|
||||
|
||||
CHECK(ffi_prep_closure(&cl, &cif, closure_test_fn2,
|
||||
CHECK(ffi_prep_closure(pcl, &cif, closure_test_fn2,
|
||||
(void *) 3 /* userdata */) == FFI_OK);
|
||||
|
||||
CHECK((*((closure_test_type2)(&cl)))
|
||||
CHECK((*((closure_test_type2)pcl))
|
||||
(1, 2, 3, 4, 127, 5, 6, 8, 9, 10, 11, 12.0, 13,
|
||||
19.0, 21, 1) == 255);
|
||||
|
||||
@ -1284,10 +1292,10 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
|
||||
&ffi_type_sint, cl_arg_types) == FFI_OK);
|
||||
|
||||
CHECK(ffi_prep_closure(&cl, &cif, closure_test_fn3,
|
||||
CHECK(ffi_prep_closure(pcl, &cif, closure_test_fn3,
|
||||
(void *) 3 /* userdata */) == FFI_OK);
|
||||
|
||||
CHECK((*((closure_test_type3)(&cl)))
|
||||
CHECK((*((closure_test_type3)pcl))
|
||||
(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9, 10, 11.11, 12.0, 13,
|
||||
19.19, 21.21, 1) == 135);
|
||||
}
|
||||
|
@ -31,7 +31,15 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 1)
|
||||
# define hidden __attribute__ ((visibility ("hidden")))
|
||||
#else
|
||||
# define hidden
|
||||
#endif
|
||||
|
||||
|
||||
extern void ffi_closure_SYSV(void);
|
||||
extern void hidden ffi_closure_LINUX64(void);
|
||||
|
||||
enum {
|
||||
/* The assembly depends on these exact flags. */
|
||||
@ -52,7 +60,7 @@ enum {
|
||||
};
|
||||
enum { ASM_NEEDS_REGISTERS = 4 };
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
/* ffi_prep_args_SYSV 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:
|
||||
@ -79,7 +87,7 @@ enum { ASM_NEEDS_REGISTERS = 4 };
|
||||
*/
|
||||
|
||||
/*@-exportheader@*/
|
||||
void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
|
||||
void ffi_prep_args_SYSV(extended_cif *ecif, unsigned *const stack)
|
||||
/*@=exportheader@*/
|
||||
{
|
||||
const unsigned bytes = ecif->cif->bytes;
|
||||
@ -124,7 +132,7 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
|
||||
/* Deal with return values that are actually pass-by-reference. */
|
||||
if (flags & FLAG_RETVAL_REFERENCE)
|
||||
{
|
||||
*gpr_base++ = (unsigned)(char *)ecif->rvalue;
|
||||
*gpr_base++ = (unsigned long)(char *)ecif->rvalue;
|
||||
intarg_count++;
|
||||
}
|
||||
|
||||
@ -210,7 +218,7 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
|
||||
copy_space -= struct_copy_size;
|
||||
memcpy(copy_space, (char *)*p_argv, (*ptr)->size);
|
||||
|
||||
gprvalue = (unsigned)copy_space;
|
||||
gprvalue = (unsigned long)copy_space;
|
||||
|
||||
FFI_ASSERT(copy_space > (char *)next_arg);
|
||||
FFI_ASSERT(flags & FLAG_ARG_NEEDS_COPY);
|
||||
@ -252,34 +260,229 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
|
||||
FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
|
||||
}
|
||||
|
||||
/* About the LINUX64 ABI. */
|
||||
enum {
|
||||
NUM_GPR_ARG_REGISTERS64 = 8,
|
||||
NUM_FPR_ARG_REGISTERS64 = 13
|
||||
};
|
||||
enum { ASM_NEEDS_REGISTERS64 = 4 };
|
||||
|
||||
/* ffi_prep_args64 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:
|
||||
|
||||
| Ret addr from ffi_call_LINUX64 8bytes | higher addresses
|
||||
|--------------------------------------------|
|
||||
| CR save area 8bytes |
|
||||
|--------------------------------------------|
|
||||
| Previous backchain pointer 8 | stack pointer here
|
||||
|--------------------------------------------|<+ <<< on entry to
|
||||
| Saved r28-r31 4*8 | | ffi_call_LINUX64
|
||||
|--------------------------------------------| |
|
||||
| GPR registers r3-r10 8*8 | |
|
||||
|--------------------------------------------| |
|
||||
| FPR registers f1-f13 (optional) 13*8 | |
|
||||
|--------------------------------------------| |
|
||||
| Parameter save area | |
|
||||
|--------------------------------------------| |
|
||||
| TOC save area 8 | |
|
||||
|--------------------------------------------| | stack |
|
||||
| Linker doubleword 8 | | gorws |
|
||||
|--------------------------------------------| | down V
|
||||
| Compiler doubleword 8 | |
|
||||
|--------------------------------------------| | lower addresses
|
||||
| Space for callee's LR 8 | |
|
||||
|--------------------------------------------| |
|
||||
| CR save area 8 | |
|
||||
|--------------------------------------------| | stack pointer here
|
||||
| Current backchain pointer 8 |-/ during
|
||||
|--------------------------------------------| <<< ffi_call_LINUX64
|
||||
|
||||
*/
|
||||
|
||||
/*@-exportheader@*/
|
||||
void hidden ffi_prep_args64(extended_cif *ecif, unsigned long *const stack)
|
||||
/*@=exportheader@*/
|
||||
{
|
||||
const unsigned long bytes = ecif->cif->bytes;
|
||||
const unsigned long flags = ecif->cif->flags;
|
||||
|
||||
/* 'stacktop' points at the previous backchain pointer. */
|
||||
unsigned long *const stacktop = stack + (bytes / sizeof(unsigned long));
|
||||
|
||||
/* 'next_arg' points at the space for gpr3, and grows upwards as
|
||||
we use GPR registers, then continues at rest. */
|
||||
unsigned long *const gpr_base = stacktop - ASM_NEEDS_REGISTERS64
|
||||
- NUM_GPR_ARG_REGISTERS64;
|
||||
unsigned long *const gpr_end = gpr_base + NUM_GPR_ARG_REGISTERS64;
|
||||
unsigned long *const rest = stack + 6 + NUM_GPR_ARG_REGISTERS64;
|
||||
unsigned long *next_arg = gpr_base;
|
||||
|
||||
/* 'fpr_base' points at the space for fpr3, and grows upwards as
|
||||
we use FPR registers. */
|
||||
double *fpr_base = (double *)gpr_base - NUM_FPR_ARG_REGISTERS64;
|
||||
int fparg_count = 0;
|
||||
|
||||
int i, words;
|
||||
ffi_type **ptr;
|
||||
double double_tmp;
|
||||
void **p_argv;
|
||||
unsigned long gprvalue;
|
||||
|
||||
/* Check that everything starts aligned properly. */
|
||||
FFI_ASSERT(((unsigned long)(char *)stack & 0xF) == 0);
|
||||
FFI_ASSERT(((unsigned long)(char *)stacktop & 0xF) == 0);
|
||||
FFI_ASSERT((bytes & 0xF) == 0);
|
||||
|
||||
/* Deal with return values that are actually pass-by-reference. */
|
||||
if (flags & FLAG_RETVAL_REFERENCE)
|
||||
*next_arg++ = (unsigned long)(char *)ecif->rvalue;
|
||||
|
||||
/* Now for the arguments. */
|
||||
p_argv = ecif->avalue;
|
||||
for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
|
||||
i > 0;
|
||||
i--, ptr++, p_argv++)
|
||||
{
|
||||
switch ((*ptr)->type)
|
||||
{
|
||||
case FFI_TYPE_FLOAT:
|
||||
double_tmp = *(float *)*p_argv;
|
||||
*(float *)next_arg = (float)double_tmp;
|
||||
if (++next_arg == gpr_end)
|
||||
next_arg = rest;
|
||||
if (fparg_count < NUM_FPR_ARG_REGISTERS64)
|
||||
*fpr_base++ = double_tmp;
|
||||
fparg_count++;
|
||||
FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
double_tmp = *(double *)*p_argv;
|
||||
*(double *)next_arg = double_tmp;
|
||||
if (++next_arg == gpr_end)
|
||||
next_arg = rest;
|
||||
if (fparg_count < NUM_FPR_ARG_REGISTERS64)
|
||||
*fpr_base++ = double_tmp;
|
||||
fparg_count++;
|
||||
FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
#endif
|
||||
words = ((*ptr)->size + 7) / 8;
|
||||
if (next_arg >= gpr_base && next_arg + words > gpr_end)
|
||||
{
|
||||
unsigned int first = (char *) gpr_end - (char *) next_arg;
|
||||
memcpy((char *) next_arg, (char *) *p_argv, first);
|
||||
memcpy((char *) rest, (char *) *p_argv + first,
|
||||
(*ptr)->size - first);
|
||||
next_arg = rest + words * 8 - first;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Structures with 1, 2 and 4 byte sizes are passed left-padded
|
||||
if they are in the first 8 arguments. */
|
||||
if (next_arg >= gpr_base
|
||||
&& (*ptr)->size < 8
|
||||
&& ((*ptr)->size & ~((*ptr)->size - 1)) == (*ptr)->size)
|
||||
memcpy((char *) next_arg + 8 - (*ptr)->size,
|
||||
(char *) *p_argv, (*ptr)->size);
|
||||
else
|
||||
memcpy((char *) next_arg, (char *) *p_argv, (*ptr)->size);
|
||||
next_arg += words;
|
||||
if (next_arg == gpr_end)
|
||||
next_arg = rest;
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
gprvalue = *(unsigned char *)*p_argv;
|
||||
goto putgpr;
|
||||
case FFI_TYPE_SINT8:
|
||||
gprvalue = *(signed char *)*p_argv;
|
||||
goto putgpr;
|
||||
case FFI_TYPE_UINT16:
|
||||
gprvalue = *(unsigned short *)*p_argv;
|
||||
goto putgpr;
|
||||
case FFI_TYPE_SINT16:
|
||||
gprvalue = *(signed short *)*p_argv;
|
||||
goto putgpr;
|
||||
case FFI_TYPE_UINT32:
|
||||
gprvalue = *(unsigned int *)*p_argv;
|
||||
goto putgpr;
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_SINT32:
|
||||
gprvalue = *(signed int *)*p_argv;
|
||||
goto putgpr;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_POINTER:
|
||||
gprvalue = *(unsigned long *)*p_argv;
|
||||
putgpr:
|
||||
*next_arg++ = gprvalue;
|
||||
if (next_arg == gpr_end)
|
||||
next_arg = rest;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS
|
||||
|| (next_arg >= gpr_base && next_arg <= gpr_base + 4));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
/* All this is for the SYSV ABI. */
|
||||
/* All this is for the SYSV and LINUX64 ABI. */
|
||||
int i;
|
||||
ffi_type **ptr;
|
||||
unsigned bytes;
|
||||
int fparg_count = 0, intarg_count = 0;
|
||||
unsigned flags = 0;
|
||||
unsigned struct_copy_size = 0;
|
||||
|
||||
/* All the machine-independent calculation of cif->bytes will be wrong.
|
||||
Redo the calculation for SYSV. */
|
||||
|
||||
/* Space for the frame pointer, callee's LR, and the asm's temp regs. */
|
||||
bytes = (2 + ASM_NEEDS_REGISTERS) * sizeof(int);
|
||||
if (cif->abi != FFI_LINUX64)
|
||||
{
|
||||
/* All the machine-independent calculation of cif->bytes will be wrong.
|
||||
Redo the calculation for SYSV. */
|
||||
|
||||
/* Space for the GPR registers. */
|
||||
bytes += NUM_GPR_ARG_REGISTERS * sizeof(int);
|
||||
/* Space for the frame pointer, callee's LR, and the asm's temp regs. */
|
||||
bytes = (2 + ASM_NEEDS_REGISTERS) * sizeof(int);
|
||||
|
||||
/* Return value handling. The rules are as follows:
|
||||
/* Space for the GPR registers. */
|
||||
bytes += NUM_GPR_ARG_REGISTERS * sizeof(int);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 64-bit ABI. */
|
||||
|
||||
/* Space for backchain, CR, LR, cc/ld doubleword, TOC and the asm's temp
|
||||
regs. */
|
||||
bytes = (6 + ASM_NEEDS_REGISTERS64) * sizeof(long);
|
||||
|
||||
/* Space for the mandatory parm save area and general registers. */
|
||||
bytes += 2 * NUM_GPR_ARG_REGISTERS64 * sizeof(long);
|
||||
}
|
||||
|
||||
/* Return value handling. The rules for SYSV are as follows:
|
||||
- 32-bit (or less) integer values are returned in gpr3;
|
||||
- Structures of size <= 4 bytes also returned in gpr3;
|
||||
- 64-bit integer values and structures between 5 and 8 bytes are returned
|
||||
in gpr3 and gpr4;
|
||||
- Single/double FP values are returned in fpr1;
|
||||
- Larger structures and long double (if not equivalent to double) values
|
||||
are allocated space and a pointer is passed as the first argument. */
|
||||
are allocated space and a pointer is passed as the first argument.
|
||||
For LINUX64:
|
||||
- integer values in gpr3;
|
||||
- Structures/Unions and long double by reference;
|
||||
- Single/double FP values in fpr1. */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_DOUBLE:
|
||||
@ -295,7 +498,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
if (cif->abi != FFI_GCC_SYSV)
|
||||
if (cif->abi != FFI_GCC_SYSV && cif->abi != FFI_LINUX64)
|
||||
if (cif->rtype->size <= 4)
|
||||
break;
|
||||
else if (cif->rtype->size <= 8)
|
||||
@ -319,59 +522,86 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
break;
|
||||
}
|
||||
|
||||
/* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
|
||||
first NUM_FPR_ARG_REGISTERS fp 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:
|
||||
fparg_count++;
|
||||
/* floating singles are not 8-aligned on stack */
|
||||
break;
|
||||
if (cif->abi != FFI_LINUX64)
|
||||
/* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
|
||||
first NUM_FPR_ARG_REGISTERS fp 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:
|
||||
fparg_count++;
|
||||
/* floating singles are not 8-aligned on stack */
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
fparg_count++;
|
||||
/* If this FP arg is going on the stack, it must be
|
||||
8-byte-aligned. */
|
||||
if (fparg_count > NUM_FPR_ARG_REGISTERS
|
||||
&& intarg_count%2 != 0)
|
||||
intarg_count++;
|
||||
break;
|
||||
case FFI_TYPE_DOUBLE:
|
||||
fparg_count++;
|
||||
/* If this FP arg is going on the stack, it must be
|
||||
8-byte-aligned. */
|
||||
if (fparg_count > NUM_FPR_ARG_REGISTERS
|
||||
&& intarg_count%2 != 0)
|
||||
intarg_count++;
|
||||
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 (intarg_count == NUM_GPR_ARG_REGISTERS-1
|
||||
|| intarg_count >= NUM_GPR_ARG_REGISTERS && intarg_count%2 != 0)
|
||||
intarg_count++;
|
||||
intarg_count += 2;
|
||||
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 (intarg_count == NUM_GPR_ARG_REGISTERS-1
|
||||
|| (intarg_count >= NUM_GPR_ARG_REGISTERS
|
||||
&& intarg_count%2 != 0))
|
||||
intarg_count++;
|
||||
intarg_count += 2;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
case FFI_TYPE_STRUCT:
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
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). */
|
||||
struct_copy_size += ((*ptr)->size + 15) & ~0xF;
|
||||
/* Fall through (allocate space for the pointer). */
|
||||
/* 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). */
|
||||
struct_copy_size += ((*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. */
|
||||
intarg_count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
/* Everything else is passed as a 4-byte word in a GPR, either
|
||||
the object itself or a pointer to it. */
|
||||
intarg_count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
||||
{
|
||||
switch ((*ptr)->type)
|
||||
{
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
fparg_count++;
|
||||
intarg_count++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
#endif
|
||||
intarg_count += ((*ptr)->size + 7) & ~7;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Everything else is passed as a 8-byte word in a GPR, either
|
||||
the object itself or a pointer to it. */
|
||||
intarg_count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fparg_count != 0)
|
||||
flags |= FLAG_FP_ARGUMENTS;
|
||||
@ -379,16 +609,29 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
flags |= FLAG_4_GPR_ARGUMENTS;
|
||||
if (struct_copy_size != 0)
|
||||
flags |= FLAG_ARG_NEEDS_COPY;
|
||||
|
||||
/* Space for the FPR registers, if needed. */
|
||||
if (fparg_count != 0)
|
||||
bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
|
||||
|
||||
/* Stack space. */
|
||||
if (intarg_count > NUM_GPR_ARG_REGISTERS)
|
||||
bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof(int);
|
||||
if (fparg_count > NUM_FPR_ARG_REGISTERS)
|
||||
bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof(double);
|
||||
if (cif->abi != FFI_LINUX64)
|
||||
{
|
||||
/* Space for the FPR registers, if needed. */
|
||||
if (fparg_count != 0)
|
||||
bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
|
||||
|
||||
/* Stack space. */
|
||||
if (intarg_count > NUM_GPR_ARG_REGISTERS)
|
||||
bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof(int);
|
||||
if (fparg_count > NUM_FPR_ARG_REGISTERS)
|
||||
bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof(double);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Space for the FPR registers, if needed. */
|
||||
if (fparg_count != 0)
|
||||
bytes += NUM_FPR_ARG_REGISTERS64 * sizeof(double);
|
||||
|
||||
/* Stack space. */
|
||||
if (intarg_count > NUM_GPR_ARG_REGISTERS64)
|
||||
bytes += (intarg_count - NUM_GPR_ARG_REGISTERS64) * sizeof(long);
|
||||
}
|
||||
|
||||
/* The stack space allocated needs to be a multiple of 16 bytes. */
|
||||
bytes = (bytes + 15) & ~0xF;
|
||||
@ -408,6 +651,10 @@ extern void ffi_call_SYSV(/*@out@*/ extended_cif *,
|
||||
unsigned, unsigned,
|
||||
/*@out@*/ unsigned *,
|
||||
void (*fn)());
|
||||
extern void hidden ffi_call_LINUX64(/*@out@*/ extended_cif *,
|
||||
unsigned long, unsigned long,
|
||||
/*@out@*/ unsigned long *,
|
||||
void (*fn)());
|
||||
/*@=declundef@*/
|
||||
/*@=exportheader@*/
|
||||
|
||||
@ -437,6 +684,7 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
#ifndef POWERPC64
|
||||
case FFI_SYSV:
|
||||
case FFI_GCC_SYSV:
|
||||
/*@-usedef@*/
|
||||
@ -444,6 +692,14 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
/*@=usedef@*/
|
||||
break;
|
||||
#else
|
||||
case FFI_LINUX64:
|
||||
/*@-usedef@*/
|
||||
ffi_call_LINUX64(&ecif, -(long) cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
/*@=usedef@*/
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
@ -451,14 +707,38 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
}
|
||||
|
||||
|
||||
#ifndef POWERPC64
|
||||
static void flush_icache(char *, int);
|
||||
|
||||
#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");
|
||||
}
|
||||
#endif
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data)
|
||||
{
|
||||
#ifdef POWERPC64
|
||||
void **tramp = (void **) &closure->tramp[0];
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_LINUX64);
|
||||
/* Copy function address and TOC from ffi_closure_LINUX64. */
|
||||
memcpy (tramp, (char *) ffi_closure_LINUX64, 16);
|
||||
tramp[2] = (void *) closure;
|
||||
#else
|
||||
unsigned int *tramp;
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
|
||||
@ -475,34 +755,25 @@ ffi_prep_closure (ffi_closure* closure,
|
||||
*(void **) &tramp[2] = (void *)ffi_closure_SYSV; /* function */
|
||||
*(void **) &tramp[3] = (void *)closure; /* context */
|
||||
|
||||
/* Flush the icache. */
|
||||
flush_icache(&closure->tramp[0],FFI_TRAMPOLINE_SIZE);
|
||||
#endif
|
||||
|
||||
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)
|
||||
typedef union
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
float f;
|
||||
double d;
|
||||
} ffi_dblfl;
|
||||
|
||||
int ffi_closure_helper_SYSV (ffi_closure*, void*, unsigned long*,
|
||||
unsigned long*, unsigned long*);
|
||||
ffi_dblfl*, unsigned long*);
|
||||
|
||||
/* Basically the trampoline invokes ffi_closure_SYSV, and on
|
||||
* entry, r11 holds the address of the closure.
|
||||
@ -514,7 +785,7 @@ int ffi_closure_helper_SYSV (ffi_closure*, void*, unsigned long*,
|
||||
|
||||
int
|
||||
ffi_closure_helper_SYSV (ffi_closure* closure, void * rvalue,
|
||||
unsigned long * pgr, unsigned long * pfr,
|
||||
unsigned long * pgr, ffi_dblfl * pfr,
|
||||
unsigned long * pst)
|
||||
{
|
||||
/* rvalue is the pointer to space for return value in closure assembly */
|
||||
@ -540,7 +811,7 @@ ffi_closure_helper_SYSV (ffi_closure* closure, void * rvalue,
|
||||
returns the data directly to the caller. */
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
rvalue = *pgr;
|
||||
rvalue = (void *) *pgr;
|
||||
ng++;
|
||||
pgr++;
|
||||
}
|
||||
@ -631,11 +902,11 @@ ffi_closure_helper_SYSV (ffi_closure* closure, void * rvalue,
|
||||
/* there are 8 64bit floating point registers */
|
||||
|
||||
if (nf < 8) {
|
||||
temp = *(double*)pfr;
|
||||
*(float*)pfr = (float)temp;
|
||||
temp = pfr->d;
|
||||
pfr->f = (float)temp;
|
||||
avalue[i] = pfr;
|
||||
nf++;
|
||||
pfr+=2;
|
||||
pfr++;
|
||||
} else {
|
||||
/* FIXME? here we are really changing the values
|
||||
* stored in the original calling routines outgoing
|
||||
@ -655,7 +926,7 @@ ffi_closure_helper_SYSV (ffi_closure* closure, void * rvalue,
|
||||
if (nf < 8) {
|
||||
avalue[i] = pfr;
|
||||
nf++;
|
||||
pfr+=2;
|
||||
pfr++;
|
||||
} else {
|
||||
if (((long)pst) & 4) pst++;
|
||||
avalue[i] = pst;
|
||||
@ -674,12 +945,148 @@ ffi_closure_helper_SYSV (ffi_closure* closure, void * rvalue,
|
||||
|
||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
/* Tell ffi_closure_osf how to perform return type promotions. */
|
||||
/* Tell ffi_closure_SYSV how to perform return type promotions. */
|
||||
return cif->rtype->type;
|
||||
|
||||
}
|
||||
|
||||
int hidden ffi_closure_helper_LINUX64 (ffi_closure*, void*, unsigned long*,
|
||||
ffi_dblfl*);
|
||||
|
||||
int hidden
|
||||
ffi_closure_helper_LINUX64 (ffi_closure* closure, void * rvalue,
|
||||
unsigned long * pst, ffi_dblfl * pfr)
|
||||
{
|
||||
/* rvalue is the pointer to space for return value in closure assembly */
|
||||
/* pst is the pointer to parameter save area
|
||||
(r3-r10 are stored into its first 8 slots by ffi_closure_LINUX64) */
|
||||
/* pfr is the pointer to where f1-f13 are stored in ffi_closure_LINUX64 */
|
||||
|
||||
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 = (void *) *pst;
|
||||
ng++;
|
||||
pst++;
|
||||
}
|
||||
|
||||
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:
|
||||
avalue[i] = (char *) pst + 7;
|
||||
ng++;
|
||||
pst++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
avalue[i] = (char *) pst + 6;
|
||||
ng++;
|
||||
pst++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
avalue[i] = (char *) pst + 4;
|
||||
ng++;
|
||||
pst++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_POINTER:
|
||||
avalue[i] = pst;
|
||||
ng++;
|
||||
pst++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
#endif
|
||||
/* Structures with 1, 2 and 4 byte sizes are passed left-padded
|
||||
if they are in the first 8 arguments. */
|
||||
if (ng < NUM_GPR_ARG_REGISTERS64
|
||||
&& arg_types[i]->size < 8
|
||||
&& ((arg_types[i]->size & ~(arg_types[i]->size - 1))
|
||||
== arg_types[i]->size))
|
||||
avalue[i] = (char *) pst + 8 - arg_types[i]->size;
|
||||
else
|
||||
avalue[i] = pst;
|
||||
ng += (arg_types[i]->size + 7) / 8;
|
||||
pst += (arg_types[i]->size + 7) / 8;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
/* unfortunately float values are stored as doubles
|
||||
* in the ffi_closure_LINUX64 code (since we don't check
|
||||
* the type in that routine).
|
||||
*/
|
||||
|
||||
/* there are 13 64bit floating point registers */
|
||||
|
||||
if (nf < NUM_FPR_ARG_REGISTERS64) {
|
||||
temp = pfr->d;
|
||||
pfr->f = (float)temp;
|
||||
avalue[i] = pfr;
|
||||
pfr++;
|
||||
} else {
|
||||
avalue[i] = pst;
|
||||
}
|
||||
nf++;
|
||||
ng++;
|
||||
pst++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
/* On the outgoing stack all values are aligned to 8 */
|
||||
/* there are 13 64bit floating point registers */
|
||||
|
||||
if (nf < NUM_FPR_ARG_REGISTERS64) {
|
||||
avalue[i] = pfr;
|
||||
pfr++;
|
||||
} else {
|
||||
avalue[i] = pst;
|
||||
}
|
||||
nf++;
|
||||
ng++;
|
||||
pst++;
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
/* Tell ffi_closure_LINUX64 how to perform return type promotions. */
|
||||
return cif->rtype->type;
|
||||
|
||||
}
|
||||
|
185
libffi/src/powerpc/linux64.S
Normal file
185
libffi/src/powerpc/linux64.S
Normal file
@ -0,0 +1,185 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PowerPC64 Assembly glue.
|
||||
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <ffi.h>
|
||||
|
||||
#ifdef __powerpc64__
|
||||
.hidden ffi_call_LINUX64, .ffi_call_LINUX64
|
||||
.globl ffi_call_LINUX64, .ffi_call_LINUX64
|
||||
.section ".opd","aw"
|
||||
.align 3
|
||||
ffi_call_LINUX64:
|
||||
.quad .ffi_call_LINUX64,.TOC.@tocbase,0
|
||||
.size ffi_call_LINUX64,24
|
||||
.type .ffi_call_LINUX64,@function
|
||||
.text
|
||||
.ffi_call_LINUX64:
|
||||
.LFB1:
|
||||
mflr %r0
|
||||
std %r28, -32(%r1)
|
||||
std %r29, -24(%r1)
|
||||
std %r30, -16(%r1)
|
||||
std %r31, -8(%r1)
|
||||
std %r0, 16(%r1)
|
||||
|
||||
mr %r28, %r1 /* our AP. */
|
||||
stdux %r1, %r1, %r4
|
||||
.LCFI0:
|
||||
mr %r31, %r5 /* flags, */
|
||||
mr %r30, %r6 /* rvalue, */
|
||||
mr %r29, %r7 /* function address. */
|
||||
std %r2, 40(%r1)
|
||||
|
||||
/* Call ffi_prep_args64. */
|
||||
mr %r4, %r1
|
||||
bl .ffi_prep_args64
|
||||
|
||||
ld %r0, 0(%r29)
|
||||
ld %r2, 8(%r29)
|
||||
ld %r11, 16(%r29)
|
||||
|
||||
/* Now do the call. */
|
||||
/* Set up cr1 with bits 4-7 of the flags. */
|
||||
mtcrf 0x40, %r31
|
||||
|
||||
/* Get the address to call into CTR. */
|
||||
mtctr %r0
|
||||
/* Load all those argument registers. */
|
||||
ld %r3, -32-(8*8)(%r28)
|
||||
ld %r4, -32-(7*8)(%r28)
|
||||
ld %r5, -32-(6*8)(%r28)
|
||||
ld %r6, -32-(5*8)(%r28)
|
||||
bf- 5, 1f
|
||||
ld %r7, -32-(4*4)(%r28)
|
||||
ld %r8, -32-(3*4)(%r28)
|
||||
ld %r9, -32-(2*4)(%r28)
|
||||
ld %r10, -32-(1*4)(%r28)
|
||||
1:
|
||||
|
||||
/* Load all the FP registers. */
|
||||
bf- 6, 2f
|
||||
lfd %f1, -32-(21*8)(%r28)
|
||||
lfd %f2, -32-(20*8)(%r28)
|
||||
lfd %f3, -32-(19*8)(%r28)
|
||||
lfd %f4, -32-(18*8)(%r28)
|
||||
lfd %f5, -32-(17*8)(%r28)
|
||||
lfd %f6, -32-(16*8)(%r28)
|
||||
lfd %f7, -32-(15*8)(%r28)
|
||||
lfd %f8, -32-(14*8)(%r28)
|
||||
lfd %f9, -32-(13*8)(%r28)
|
||||
lfd %f10, -32-(12*8)(%r28)
|
||||
lfd %f11, -32-(11*8)(%r28)
|
||||
lfd %f12, -32-(10*8)(%r28)
|
||||
lfd %f13, -32-(9*8)(%r28)
|
||||
2:
|
||||
/* FIXME: Shouldn't gcc use %r3-%r10 in this case
|
||||
and not the parm save area? */
|
||||
std %r3, 48+(0*8)(%r1)
|
||||
std %r4, 48+(1*8)(%r1)
|
||||
std %r5, 48+(2*8)(%r1)
|
||||
std %r6, 48+(3*8)(%r1)
|
||||
std %r7, 48+(4*8)(%r1)
|
||||
std %r8, 48+(5*8)(%r1)
|
||||
std %r9, 48+(6*8)(%r1)
|
||||
std %r10, 48+(7*8)(%r1)
|
||||
/* end of FIXME. */
|
||||
|
||||
/* Make the call. */
|
||||
bctrl
|
||||
|
||||
/* Now, deal with the return value. */
|
||||
mtcrf 0x01, %r31
|
||||
bt- 30, .Ldone_return_value
|
||||
bt- 29, .Lfp_return_value
|
||||
std %r3, 0(%r30)
|
||||
/* Fall through... */
|
||||
|
||||
.Ldone_return_value:
|
||||
/* Restore the registers we used and return. */
|
||||
ld %r2, 40(%r1)
|
||||
mr %r1, %r28
|
||||
ld %r0, 16(%r28)
|
||||
ld %r28, -32(%r1)
|
||||
mtlr %r0
|
||||
ld %r29, -24(%r1)
|
||||
ld %r30, -16(%r1)
|
||||
ld %r31, -8(%r1)
|
||||
blr
|
||||
|
||||
.Lfp_return_value:
|
||||
bf 28, .Lfloat_return_value
|
||||
stfd %f1, 0(%r30)
|
||||
b .Ldone_return_value
|
||||
.Lfloat_return_value:
|
||||
stfs %f1, 0(%r30)
|
||||
b .Ldone_return_value
|
||||
.LFE1:
|
||||
.long 0
|
||||
.byte 0,12,0,1,128,4,0,0
|
||||
.size .ffi_call_LINUX64,.-.ffi_call_LINUX64
|
||||
|
||||
.section .eh_frame,"aw",@progbits
|
||||
.Lframe1:
|
||||
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
|
||||
.LSCIE1:
|
||||
.4byte 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.uleb128 0x1 # CIE Code Alignment Factor
|
||||
.sleb128 -8 # CIE Data Alignment Factor
|
||||
.byte 0x41 # CIE RA Column
|
||||
.uleb128 0x1 # Augmentation size
|
||||
.byte 0x14 # FDE Encoding (pcrel udata8)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1
|
||||
.uleb128 0x0
|
||||
.align 3
|
||||
.LECIE1:
|
||||
.LSFDE1:
|
||||
.4byte .LEFDE1-.LASFDE1 # FDE Length
|
||||
.LASFDE1:
|
||||
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
|
||||
.8byte .LFB1-. # FDE initial location
|
||||
.8byte .LFE1-.LFB1 # FDE address range
|
||||
.uleb128 0x0 # Augmentation size
|
||||
.byte 0x2 # DW_CFA_advance_loc1
|
||||
.byte .LCFI0-.LFB1
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.uleb128 0x1c
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x41
|
||||
.sleb128 -2
|
||||
.byte 0x9f # DW_CFA_offset, column 0x1f
|
||||
.uleb128 0x1
|
||||
.byte 0x9e # DW_CFA_offset, column 0x1e
|
||||
.uleb128 0x2
|
||||
.byte 0x9d # DW_CFA_offset, column 0x1d
|
||||
.uleb128 0x3
|
||||
.byte 0x9c # DW_CFA_offset, column 0x1c
|
||||
.uleb128 0x4
|
||||
.align 3
|
||||
.LEFDE1:
|
||||
#endif
|
210
libffi/src/powerpc/linux64_closure.S
Normal file
210
libffi/src/powerpc/linux64_closure.S
Normal file
@ -0,0 +1,210 @@
|
||||
.file "linux64_closure.S"
|
||||
|
||||
#ifdef __powerpc64__
|
||||
.hidden ffi_closure_LINUX64, .ffi_closure_LINUX64
|
||||
.globl ffi_closure_LINUX64, .ffi_closure_LINUX64
|
||||
.section ".opd","aw"
|
||||
.align 3
|
||||
ffi_closure_LINUX64:
|
||||
.quad .ffi_closure_LINUX64,.TOC.@tocbase,0
|
||||
.size ffi_closure_LINUX64,24
|
||||
.type .ffi_closure_LINUX64,@function
|
||||
.text
|
||||
.ffi_closure_LINUX64:
|
||||
.LFB1:
|
||||
# save general regs into parm save area
|
||||
std %r3, 48(%r1)
|
||||
std %r4, 56(%r1)
|
||||
std %r5, 64(%r1)
|
||||
std %r6, 72(%r1)
|
||||
mflr %r0
|
||||
|
||||
std %r7, 80(%r1)
|
||||
std %r8, 88(%r1)
|
||||
std %r9, 96(%r1)
|
||||
std %r10, 104(%r1)
|
||||
std %r0, 16(%r1)
|
||||
|
||||
# mandatory 48 bytes special reg save area + 64 bytes parm save area
|
||||
# + 8 bytes retval area + 13*8 bytes fpr save area
|
||||
stdu %r1, -224(%r1)
|
||||
.LCFI0:
|
||||
|
||||
# next save fpr 1 to fpr 13
|
||||
stfd %f1, 120+(0*8)(%r1)
|
||||
stfd %f2, 120+(1*8)(%r1)
|
||||
stfd %f3, 120+(2*8)(%r1)
|
||||
stfd %f4, 120+(3*8)(%r1)
|
||||
stfd %f5, 120+(4*8)(%r1)
|
||||
stfd %f6, 120+(5*8)(%r1)
|
||||
stfd %f7, 120+(6*8)(%r1)
|
||||
stfd %f8, 120+(7*8)(%r1)
|
||||
stfd %f9, 120+(8*8)(%r1)
|
||||
stfd %f10, 120+(9*8)(%r1)
|
||||
stfd %f11, 120+(10*8)(%r1)
|
||||
stfd %f12, 120+(11*8)(%r1)
|
||||
stfd %f13, 120+(12*8)(%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 parameter save area
|
||||
# in the previous frame
|
||||
addi %r5, %r1, 224 + 48
|
||||
|
||||
# now load up the pointer to the saved fpr registers */
|
||||
addi %r6, %r1, 120
|
||||
|
||||
# make the call
|
||||
bl .ffi_closure_helper_LINUX64
|
||||
|
||||
# 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
|
||||
bl .Lget_ret_type0_addr # get pointer to .Lret_type0 into LR
|
||||
mflr %r4 # move to r4
|
||||
sldi %r3, %r3, 4 # now multiply return type by 16
|
||||
add %r3, %r3, %r4 # add contents of table to table address
|
||||
mtctr %r3
|
||||
bctr # jump to it
|
||||
|
||||
# Each of the ret_typeX code fragments has to be exactly 16 bytes long
|
||||
# (4 instructions). For cache effectiveness we align to a 16 byte boundary
|
||||
# first.
|
||||
.align 4
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
.Lget_ret_type0_addr:
|
||||
blrl
|
||||
|
||||
.Lret_type0:
|
||||
# case FFI_TYPE_VOID
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
# case FFI_TYPE_INT
|
||||
lwa %r3, 4(%r5)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
# case FFI_TYPE_FLOAT
|
||||
lfs %f1, 4(%r5)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
# case FFI_TYPE_DOUBLE
|
||||
lfd %f1, 0(%r5)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
# case FFI_TYPE_LONGDOUBLE
|
||||
lfd %f1, 0(%r5)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
# case FFI_TYPE_UINT8
|
||||
lbz %r3, 7(%r5)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
# case FFI_TYPE_SINT8
|
||||
lbz %r3, 7(%r5)
|
||||
extsb %r3,%r3
|
||||
b .Lfinish
|
||||
nop
|
||||
# case FFI_TYPE_UINT16
|
||||
lhz %r3, 6(%r5)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
# case FFI_TYPE_SINT16
|
||||
lha %r3, 6(%r5)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
# case FFI_TYPE_UINT32
|
||||
lwz %r3, 4(%r5)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
# case FFI_TYPE_SINT32
|
||||
lwa %r3, 4(%r5)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
# case FFI_TYPE_UINT64
|
||||
ld %r3, 0(%r5)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
# case FFI_TYPE_SINT64
|
||||
ld %r3, 0(%r5)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
# case FFI_TYPE_STRUCT
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
# case FFI_TYPE_POINTER
|
||||
ld %r3, 0(%r5)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
# esac
|
||||
.Lfinish:
|
||||
ld %r0, 224+16(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 224
|
||||
blr
|
||||
.LFE1:
|
||||
.long 0
|
||||
.byte 0,12,0,1,128,0,0,0
|
||||
.size .ffi_closure_LINUX64,.-.ffi_closure_LINUX64
|
||||
|
||||
.section .eh_frame,"aw",@progbits
|
||||
.Lframe1:
|
||||
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
|
||||
.LSCIE1:
|
||||
.4byte 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.uleb128 0x1 # CIE Code Alignment Factor
|
||||
.sleb128 -8 # CIE Data Alignment Factor
|
||||
.byte 0x41 # CIE RA Column
|
||||
.uleb128 0x1 # Augmentation size
|
||||
.byte 0x14 # FDE Encoding (pcrel udata8)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1
|
||||
.uleb128 0x0
|
||||
.align 3
|
||||
.LECIE1:
|
||||
.LSFDE1:
|
||||
.4byte .LEFDE1-.LASFDE1 # FDE Length
|
||||
.LASFDE1:
|
||||
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
|
||||
.8byte .LFB1-. # FDE initial location
|
||||
.8byte .LFE1-.LFB1 # FDE address range
|
||||
.uleb128 0x0 # Augmentation size
|
||||
.byte 0x2 # DW_CFA_advance_loc1
|
||||
.byte .LCFI0-.LFB1
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 224
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x41
|
||||
.sleb128 -2
|
||||
.align 3
|
||||
.LEFDE1:
|
||||
#endif
|
@ -3,6 +3,8 @@
|
||||
|
||||
.file "ppc_closure.S"
|
||||
|
||||
#ifndef __powerpc64__
|
||||
|
||||
ENTRY(ffi_closure_SYSV)
|
||||
.LFB1:
|
||||
stwu %r1,-144(%r1)
|
||||
@ -227,3 +229,5 @@ __FRAME_BEGIN__:
|
||||
.byte 0x1 # uleb128 0x1
|
||||
.align 2
|
||||
.LEFDE1:
|
||||
|
||||
#endif
|
||||
|
@ -29,7 +29,8 @@
|
||||
#include <ffi.h>
|
||||
#include <powerpc/asm.h>
|
||||
|
||||
.globl ffi_prep_args
|
||||
#ifndef __powerpc64__
|
||||
.globl ffi_prep_args_SYSV
|
||||
ENTRY(ffi_call_SYSV)
|
||||
.LFB1:
|
||||
/* Save the old stack pointer as AP. */
|
||||
@ -58,9 +59,9 @@ ENTRY(ffi_call_SYSV)
|
||||
mr %r28,%r8 /* our AP. */
|
||||
.LCFI6:
|
||||
|
||||
/* Call ffi_prep_args. */
|
||||
/* Call ffi_prep_args_SYSV. */
|
||||
mr %r4,%r1
|
||||
bl JUMPTARGET(ffi_prep_args)
|
||||
bl JUMPTARGET(ffi_prep_args_SYSV)
|
||||
|
||||
/* Now do the call. */
|
||||
/* Set up cr1 with bits 4-7 of the flags. */
|
||||
@ -171,3 +172,4 @@ __FRAME_BEGIN__:
|
||||
.byte 0x1c /* uleb128 0x1c */
|
||||
.align 2
|
||||
.LEFDE1:
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user