Initial commit
This commit is contained in:
311
src/.svn/entries
Normal file
311
src/.svn/entries
Normal file
@@ -0,0 +1,311 @@
|
||||
10
|
||||
|
||||
dir
|
||||
152280
|
||||
svn://gcc.gnu.org/svn/gcc/trunk/libffi/src
|
||||
svn://gcc.gnu.org/svn/gcc
|
||||
|
||||
|
||||
|
||||
2009-09-28T22:26:25.100883Z
|
||||
152256
|
||||
ktietz
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
138bc75d-0d04-0410-961f-82ee72b054a4
|
||||
|
||||
arm
|
||||
dir
|
||||
|
||||
powerpc
|
||||
dir
|
||||
|
||||
closures.c
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-09-10T17:50:58.000000Z
|
||||
3c6816c5a57dc7a877a092b6c1403929
|
||||
2009-07-24T10:12:16.542948Z
|
||||
150042
|
||||
davek
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
16348
|
||||
|
||||
m32r
|
||||
dir
|
||||
|
||||
sh64
|
||||
dir
|
||||
|
||||
x86
|
||||
dir
|
||||
|
||||
alpha
|
||||
dir
|
||||
|
||||
m68k
|
||||
dir
|
||||
|
||||
types.c
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:03.000000Z
|
||||
50ac67d061e9312c64b3ed7662b64e13
|
||||
2009-06-04T15:11:12.475454Z
|
||||
148171
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
2904
|
||||
|
||||
frv
|
||||
dir
|
||||
|
||||
s390
|
||||
dir
|
||||
|
||||
cris
|
||||
dir
|
||||
|
||||
pa
|
||||
dir
|
||||
|
||||
ia64
|
||||
dir
|
||||
|
||||
raw_api.c
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:03.000000Z
|
||||
a9086fc5c1b5440f02dcbc425f093ae5
|
||||
2009-06-04T15:43:03.499507Z
|
||||
148172
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
6067
|
||||
|
||||
java_raw_api.c
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-09-16T16:25:59.000000Z
|
||||
797fe5e8686ab2b9f496e7c991ad685e
|
||||
2009-09-15T17:15:33.045042Z
|
||||
151726
|
||||
daney
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
8473
|
||||
|
||||
debug.c
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:03.000000Z
|
||||
02e0fc4e091091ebd2f78437bfd37d1b
|
||||
2009-06-04T15:11:12.475454Z
|
||||
148171
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
2233
|
||||
|
||||
sparc
|
||||
dir
|
||||
|
||||
mips
|
||||
dir
|
||||
|
||||
prep_cif.c
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:03.000000Z
|
||||
38a061bf43e144832f0aa2542dab6efb
|
||||
2009-06-04T15:11:12.475454Z
|
||||
148171
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
5318
|
||||
|
||||
dlmalloc.c
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-20T15:53:35.000000Z
|
||||
f5cc93a1921927f21dc08d81a631981d
|
||||
2009-06-12T15:57:58.721771Z
|
||||
148433
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
181631
|
||||
|
||||
sh
|
||||
dir
|
||||
|
||||
610
src/.svn/text-base/closures.c.svn-base
Normal file
610
src/.svn/text-base/closures.c.svn-base
Normal file
@@ -0,0 +1,610 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
closures.c - Copyright (c) 2007 Red Hat, Inc.
|
||||
Copyright (C) 2007 Free Software Foundation, Inc
|
||||
|
||||
Code to allocate and deallocate memory for closures.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#if defined __linux__ && !defined _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#ifndef FFI_MMAP_EXEC_WRIT
|
||||
# if __gnu_linux__
|
||||
/* This macro indicates it may be forbidden to map anonymous memory
|
||||
with both write and execute permission. Code compiled when this
|
||||
option is defined will attempt to map such pages once, but if it
|
||||
fails, it falls back to creating a temporary file in a writable and
|
||||
executable filesystem and mapping pages from it into separate
|
||||
locations in the virtual memory space, one location writable and
|
||||
another executable. */
|
||||
# define FFI_MMAP_EXEC_WRIT 1
|
||||
# define HAVE_MNTENT 1
|
||||
# endif
|
||||
# if defined(X86_WIN32) || defined(X86_WIN64)
|
||||
/* Windows systems may have Data Execution Protection (DEP) enabled,
|
||||
which requires the use of VirtualMalloc/VirtualFree to alloc/free
|
||||
executable memory. */
|
||||
# define FFI_MMAP_EXEC_WRIT 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if FFI_MMAP_EXEC_WRIT && !defined FFI_MMAP_EXEC_SELINUX
|
||||
# ifdef __linux__
|
||||
/* When defined to 1 check for SELinux and if SELinux is active,
|
||||
don't attempt PROT_EXEC|PROT_WRITE mapping at all, as that
|
||||
might cause audit messages. */
|
||||
# define FFI_MMAP_EXEC_SELINUX 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if FFI_CLOSURES
|
||||
|
||||
# if FFI_MMAP_EXEC_WRIT
|
||||
|
||||
#define USE_LOCKS 1
|
||||
#define USE_DL_PREFIX 1
|
||||
#ifdef __GNUC__
|
||||
#ifndef USE_BUILTIN_FFS
|
||||
#define USE_BUILTIN_FFS 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* We need to use mmap, not sbrk. */
|
||||
#define HAVE_MORECORE 0
|
||||
|
||||
/* We could, in theory, support mremap, but it wouldn't buy us anything. */
|
||||
#define HAVE_MREMAP 0
|
||||
|
||||
/* We have no use for this, so save some code and data. */
|
||||
#define NO_MALLINFO 1
|
||||
|
||||
/* We need all allocations to be in regular segments, otherwise we
|
||||
lose track of the corresponding code address. */
|
||||
#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
|
||||
|
||||
/* Don't allocate more than a page unless needed. */
|
||||
#define DEFAULT_GRANULARITY ((size_t)malloc_getpagesize)
|
||||
|
||||
#if FFI_CLOSURE_TEST
|
||||
/* Don't release single pages, to avoid a worst-case scenario of
|
||||
continuously allocating and releasing single pages, but release
|
||||
pairs of pages, which should do just as well given that allocations
|
||||
are likely to be small. */
|
||||
#define DEFAULT_TRIM_THRESHOLD ((size_t)malloc_getpagesize)
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#if !defined(X86_WIN32) && !defined(X86_WIN64)
|
||||
#ifdef HAVE_MNTENT
|
||||
#include <mntent.h>
|
||||
#endif /* HAVE_MNTENT */
|
||||
#include <sys/param.h>
|
||||
#include <pthread.h>
|
||||
|
||||
/* We don't want sys/mman.h to be included after we redefine mmap and
|
||||
dlmunmap. */
|
||||
#include <sys/mman.h>
|
||||
#define LACKS_SYS_MMAN_H 1
|
||||
|
||||
#if FFI_MMAP_EXEC_SELINUX
|
||||
#include <sys/statfs.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static int selinux_enabled = -1;
|
||||
|
||||
static int
|
||||
selinux_enabled_check (void)
|
||||
{
|
||||
struct statfs sfs;
|
||||
FILE *f;
|
||||
char *buf = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
if (statfs ("/selinux", &sfs) >= 0
|
||||
&& (unsigned int) sfs.f_type == 0xf97cff8cU)
|
||||
return 1;
|
||||
f = fopen ("/proc/mounts", "r");
|
||||
if (f == NULL)
|
||||
return 0;
|
||||
while (getline (&buf, &len, f) >= 0)
|
||||
{
|
||||
char *p = strchr (buf, ' ');
|
||||
if (p == NULL)
|
||||
break;
|
||||
p = strchr (p + 1, ' ');
|
||||
if (p == NULL)
|
||||
break;
|
||||
if (strncmp (p + 1, "selinuxfs ", 10) != 0)
|
||||
{
|
||||
free (buf);
|
||||
fclose (f);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
free (buf);
|
||||
fclose (f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define is_selinux_enabled() (selinux_enabled >= 0 ? selinux_enabled \
|
||||
: (selinux_enabled = selinux_enabled_check ()))
|
||||
|
||||
#else
|
||||
|
||||
#define is_selinux_enabled() 0
|
||||
|
||||
#endif /* !FFI_MMAP_EXEC_SELINUX */
|
||||
|
||||
#elif defined (__CYGWIN__)
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
/* Cygwin is Linux-like, but not quite that Linux-like. */
|
||||
#define is_selinux_enabled() 0
|
||||
|
||||
#endif /* !defined(X86_WIN32) && !defined(X86_WIN64) */
|
||||
|
||||
/* Declare all functions defined in dlmalloc.c as static. */
|
||||
static void *dlmalloc(size_t);
|
||||
static void dlfree(void*);
|
||||
static void *dlcalloc(size_t, size_t) MAYBE_UNUSED;
|
||||
static void *dlrealloc(void *, size_t) MAYBE_UNUSED;
|
||||
static void *dlmemalign(size_t, size_t) MAYBE_UNUSED;
|
||||
static void *dlvalloc(size_t) MAYBE_UNUSED;
|
||||
static int dlmallopt(int, int) MAYBE_UNUSED;
|
||||
static size_t dlmalloc_footprint(void) MAYBE_UNUSED;
|
||||
static size_t dlmalloc_max_footprint(void) MAYBE_UNUSED;
|
||||
static void** dlindependent_calloc(size_t, size_t, void**) MAYBE_UNUSED;
|
||||
static void** dlindependent_comalloc(size_t, size_t*, void**) MAYBE_UNUSED;
|
||||
static void *dlpvalloc(size_t) MAYBE_UNUSED;
|
||||
static int dlmalloc_trim(size_t) MAYBE_UNUSED;
|
||||
static size_t dlmalloc_usable_size(void*) MAYBE_UNUSED;
|
||||
static void dlmalloc_stats(void) MAYBE_UNUSED;
|
||||
|
||||
#if !(defined(X86_WIN32) || defined(X86_WIN64)) || defined (__CYGWIN__)
|
||||
/* Use these for mmap and munmap within dlmalloc.c. */
|
||||
static void *dlmmap(void *, size_t, int, int, int, off_t);
|
||||
static int dlmunmap(void *, size_t);
|
||||
#endif /* !(defined(X86_WIN32) || defined(X86_WIN64)) || defined (__CYGWIN__) */
|
||||
|
||||
#define mmap dlmmap
|
||||
#define munmap dlmunmap
|
||||
|
||||
#include "dlmalloc.c"
|
||||
|
||||
#undef mmap
|
||||
#undef munmap
|
||||
|
||||
#if !(defined(X86_WIN32) || defined(X86_WIN64)) || defined (__CYGWIN__)
|
||||
|
||||
/* A mutex used to synchronize access to *exec* variables in this file. */
|
||||
static pthread_mutex_t open_temp_exec_file_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/* A file descriptor of a temporary file from which we'll map
|
||||
executable pages. */
|
||||
static int execfd = -1;
|
||||
|
||||
/* The amount of space already allocated from the temporary file. */
|
||||
static size_t execsize = 0;
|
||||
|
||||
/* Open a temporary file name, and immediately unlink it. */
|
||||
static int
|
||||
open_temp_exec_file_name (char *name)
|
||||
{
|
||||
int fd = mkstemp (name);
|
||||
|
||||
if (fd != -1)
|
||||
unlink (name);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* Open a temporary file in the named directory. */
|
||||
static int
|
||||
open_temp_exec_file_dir (const char *dir)
|
||||
{
|
||||
static const char suffix[] = "/ffiXXXXXX";
|
||||
int lendir = strlen (dir);
|
||||
char *tempname = __builtin_alloca (lendir + sizeof (suffix));
|
||||
|
||||
if (!tempname)
|
||||
return -1;
|
||||
|
||||
memcpy (tempname, dir, lendir);
|
||||
memcpy (tempname + lendir, suffix, sizeof (suffix));
|
||||
|
||||
return open_temp_exec_file_name (tempname);
|
||||
}
|
||||
|
||||
/* Open a temporary file in the directory in the named environment
|
||||
variable. */
|
||||
static int
|
||||
open_temp_exec_file_env (const char *envvar)
|
||||
{
|
||||
const char *value = getenv (envvar);
|
||||
|
||||
if (!value)
|
||||
return -1;
|
||||
|
||||
return open_temp_exec_file_dir (value);
|
||||
}
|
||||
|
||||
#ifdef HAVE_MNTENT
|
||||
/* Open a temporary file in an executable and writable mount point
|
||||
listed in the mounts file. Subsequent calls with the same mounts
|
||||
keep searching for mount points in the same file. Providing NULL
|
||||
as the mounts file closes the file. */
|
||||
static int
|
||||
open_temp_exec_file_mnt (const char *mounts)
|
||||
{
|
||||
static const char *last_mounts;
|
||||
static FILE *last_mntent;
|
||||
|
||||
if (mounts != last_mounts)
|
||||
{
|
||||
if (last_mntent)
|
||||
endmntent (last_mntent);
|
||||
|
||||
last_mounts = mounts;
|
||||
|
||||
if (mounts)
|
||||
last_mntent = setmntent (mounts, "r");
|
||||
else
|
||||
last_mntent = NULL;
|
||||
}
|
||||
|
||||
if (!last_mntent)
|
||||
return -1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int fd;
|
||||
struct mntent mnt;
|
||||
char buf[MAXPATHLEN * 3];
|
||||
|
||||
if (getmntent_r (last_mntent, &mnt, buf, sizeof (buf)))
|
||||
return -1;
|
||||
|
||||
if (hasmntopt (&mnt, "ro")
|
||||
|| hasmntopt (&mnt, "noexec")
|
||||
|| access (mnt.mnt_dir, W_OK))
|
||||
continue;
|
||||
|
||||
fd = open_temp_exec_file_dir (mnt.mnt_dir);
|
||||
|
||||
if (fd != -1)
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_MNTENT */
|
||||
|
||||
/* Instructions to look for a location to hold a temporary file that
|
||||
can be mapped in for execution. */
|
||||
static struct
|
||||
{
|
||||
int (*func)(const char *);
|
||||
const char *arg;
|
||||
int repeat;
|
||||
} open_temp_exec_file_opts[] = {
|
||||
{ open_temp_exec_file_env, "TMPDIR", 0 },
|
||||
{ open_temp_exec_file_dir, "/tmp", 0 },
|
||||
{ open_temp_exec_file_dir, "/var/tmp", 0 },
|
||||
{ open_temp_exec_file_dir, "/dev/shm", 0 },
|
||||
{ open_temp_exec_file_env, "HOME", 0 },
|
||||
#ifdef HAVE_MNTENT
|
||||
{ open_temp_exec_file_mnt, "/etc/mtab", 1 },
|
||||
{ open_temp_exec_file_mnt, "/proc/mounts", 1 },
|
||||
#endif /* HAVE_MNTENT */
|
||||
};
|
||||
|
||||
/* Current index into open_temp_exec_file_opts. */
|
||||
static int open_temp_exec_file_opts_idx = 0;
|
||||
|
||||
/* Reset a current multi-call func, then advances to the next entry.
|
||||
If we're at the last, go back to the first and return nonzero,
|
||||
otherwise return zero. */
|
||||
static int
|
||||
open_temp_exec_file_opts_next (void)
|
||||
{
|
||||
if (open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat)
|
||||
open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func (NULL);
|
||||
|
||||
open_temp_exec_file_opts_idx++;
|
||||
if (open_temp_exec_file_opts_idx
|
||||
== (sizeof (open_temp_exec_file_opts)
|
||||
/ sizeof (*open_temp_exec_file_opts)))
|
||||
{
|
||||
open_temp_exec_file_opts_idx = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return a file descriptor of a temporary zero-sized file in a
|
||||
writable and exexutable filesystem. */
|
||||
static int
|
||||
open_temp_exec_file (void)
|
||||
{
|
||||
int fd;
|
||||
|
||||
do
|
||||
{
|
||||
fd = open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func
|
||||
(open_temp_exec_file_opts[open_temp_exec_file_opts_idx].arg);
|
||||
|
||||
if (!open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat
|
||||
|| fd == -1)
|
||||
{
|
||||
if (open_temp_exec_file_opts_next ())
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (fd == -1);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* Map in a chunk of memory from the temporary exec file into separate
|
||||
locations in the virtual memory address space, one writable and one
|
||||
executable. Returns the address of the writable portion, after
|
||||
storing an offset to the corresponding executable portion at the
|
||||
last word of the requested chunk. */
|
||||
static void *
|
||||
dlmmap_locked (void *start, size_t length, int prot, int flags, off_t offset)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
if (execfd == -1)
|
||||
{
|
||||
open_temp_exec_file_opts_idx = 0;
|
||||
retry_open:
|
||||
execfd = open_temp_exec_file ();
|
||||
if (execfd == -1)
|
||||
return MFAIL;
|
||||
}
|
||||
|
||||
offset = execsize;
|
||||
|
||||
if (ftruncate (execfd, offset + length))
|
||||
return MFAIL;
|
||||
|
||||
flags &= ~(MAP_PRIVATE | MAP_ANONYMOUS);
|
||||
flags |= MAP_SHARED;
|
||||
|
||||
ptr = mmap (NULL, length, (prot & ~PROT_WRITE) | PROT_EXEC,
|
||||
flags, execfd, offset);
|
||||
if (ptr == MFAIL)
|
||||
{
|
||||
if (!offset)
|
||||
{
|
||||
close (execfd);
|
||||
goto retry_open;
|
||||
}
|
||||
ftruncate (execfd, offset);
|
||||
return MFAIL;
|
||||
}
|
||||
else if (!offset
|
||||
&& open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat)
|
||||
open_temp_exec_file_opts_next ();
|
||||
|
||||
start = mmap (start, length, prot, flags, execfd, offset);
|
||||
|
||||
if (start == MFAIL)
|
||||
{
|
||||
munmap (ptr, length);
|
||||
ftruncate (execfd, offset);
|
||||
return start;
|
||||
}
|
||||
|
||||
mmap_exec_offset ((char *)start, length) = (char*)ptr - (char*)start;
|
||||
|
||||
execsize += length;
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
/* Map in a writable and executable chunk of memory if possible.
|
||||
Failing that, fall back to dlmmap_locked. */
|
||||
static void *
|
||||
dlmmap (void *start, size_t length, int prot,
|
||||
int flags, int fd, off_t offset)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
assert (start == NULL && length % malloc_getpagesize == 0
|
||||
&& prot == (PROT_READ | PROT_WRITE)
|
||||
&& flags == (MAP_PRIVATE | MAP_ANONYMOUS)
|
||||
&& fd == -1 && offset == 0);
|
||||
|
||||
#if FFI_CLOSURE_TEST
|
||||
printf ("mapping in %zi\n", length);
|
||||
#endif
|
||||
|
||||
if (execfd == -1 && !is_selinux_enabled ())
|
||||
{
|
||||
ptr = mmap (start, length, prot | PROT_EXEC, flags, fd, offset);
|
||||
|
||||
if (ptr != MFAIL || (errno != EPERM && errno != EACCES))
|
||||
/* Cool, no need to mess with separate segments. */
|
||||
return ptr;
|
||||
|
||||
/* If MREMAP_DUP is ever introduced and implemented, try mmap
|
||||
with ((prot & ~PROT_WRITE) | PROT_EXEC) and mremap with
|
||||
MREMAP_DUP and prot at this point. */
|
||||
}
|
||||
|
||||
if (execsize == 0 || execfd == -1)
|
||||
{
|
||||
pthread_mutex_lock (&open_temp_exec_file_mutex);
|
||||
ptr = dlmmap_locked (start, length, prot, flags, offset);
|
||||
pthread_mutex_unlock (&open_temp_exec_file_mutex);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
return dlmmap_locked (start, length, prot, flags, offset);
|
||||
}
|
||||
|
||||
/* Release memory at the given address, as well as the corresponding
|
||||
executable page if it's separate. */
|
||||
static int
|
||||
dlmunmap (void *start, size_t length)
|
||||
{
|
||||
/* We don't bother decreasing execsize or truncating the file, since
|
||||
we can't quite tell whether we're unmapping the end of the file.
|
||||
We don't expect frequent deallocation anyway. If we did, we
|
||||
could locate pages in the file by writing to the pages being
|
||||
deallocated and checking that the file contents change.
|
||||
Yuck. */
|
||||
msegmentptr seg = segment_holding (gm, start);
|
||||
void *code;
|
||||
|
||||
#if FFI_CLOSURE_TEST
|
||||
printf ("unmapping %zi\n", length);
|
||||
#endif
|
||||
|
||||
if (seg && (code = add_segment_exec_offset (start, seg)) != start)
|
||||
{
|
||||
int ret = munmap (code, length);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return munmap (start, length);
|
||||
}
|
||||
|
||||
#if FFI_CLOSURE_FREE_CODE
|
||||
/* Return segment holding given code address. */
|
||||
static msegmentptr
|
||||
segment_holding_code (mstate m, char* addr)
|
||||
{
|
||||
msegmentptr sp = &m->seg;
|
||||
for (;;) {
|
||||
if (addr >= add_segment_exec_offset (sp->base, sp)
|
||||
&& addr < add_segment_exec_offset (sp->base, sp) + sp->size)
|
||||
return sp;
|
||||
if ((sp = sp->next) == 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !(defined(X86_WIN32) || defined(X86_WIN64)) || defined (__CYGWIN__) */
|
||||
|
||||
/* Allocate a chunk of memory with the given size. Returns a pointer
|
||||
to the writable address, and sets *CODE to the executable
|
||||
corresponding virtual address. */
|
||||
void *
|
||||
ffi_closure_alloc (size_t size, void **code)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
if (!code)
|
||||
return NULL;
|
||||
|
||||
ptr = dlmalloc (size);
|
||||
|
||||
if (ptr)
|
||||
{
|
||||
msegmentptr seg = segment_holding (gm, ptr);
|
||||
|
||||
*code = add_segment_exec_offset (ptr, seg);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* Release a chunk of memory allocated with ffi_closure_alloc. If
|
||||
FFI_CLOSURE_FREE_CODE is nonzero, the given address can be the
|
||||
writable or the executable address given. Otherwise, only the
|
||||
writable address can be provided here. */
|
||||
void
|
||||
ffi_closure_free (void *ptr)
|
||||
{
|
||||
#if FFI_CLOSURE_FREE_CODE
|
||||
msegmentptr seg = segment_holding_code (gm, ptr);
|
||||
|
||||
if (seg)
|
||||
ptr = sub_segment_exec_offset (ptr, seg);
|
||||
#endif
|
||||
|
||||
dlfree (ptr);
|
||||
}
|
||||
|
||||
|
||||
#if FFI_CLOSURE_TEST
|
||||
/* Do some internal sanity testing to make sure allocation and
|
||||
deallocation of pages are working as intended. */
|
||||
int main ()
|
||||
{
|
||||
void *p[3];
|
||||
#define GET(idx, len) do { p[idx] = dlmalloc (len); printf ("allocated %zi for p[%i]\n", (len), (idx)); } while (0)
|
||||
#define PUT(idx) do { printf ("freeing p[%i]\n", (idx)); dlfree (p[idx]); } while (0)
|
||||
GET (0, malloc_getpagesize / 2);
|
||||
GET (1, 2 * malloc_getpagesize - 64 * sizeof (void*));
|
||||
PUT (1);
|
||||
GET (1, 2 * malloc_getpagesize);
|
||||
GET (2, malloc_getpagesize / 2);
|
||||
PUT (1);
|
||||
PUT (0);
|
||||
PUT (2);
|
||||
return 0;
|
||||
}
|
||||
#endif /* FFI_CLOSURE_TEST */
|
||||
# else /* ! FFI_MMAP_EXEC_WRIT */
|
||||
|
||||
/* On many systems, memory returned by malloc is writable and
|
||||
executable, so just use it. */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
void *
|
||||
ffi_closure_alloc (size_t size, void **code)
|
||||
{
|
||||
if (!code)
|
||||
return NULL;
|
||||
|
||||
return *code = malloc (size);
|
||||
}
|
||||
|
||||
void
|
||||
ffi_closure_free (void *ptr)
|
||||
{
|
||||
free (ptr);
|
||||
}
|
||||
|
||||
# endif /* ! FFI_MMAP_EXEC_WRIT */
|
||||
#endif /* FFI_CLOSURES */
|
||||
59
src/.svn/text-base/debug.c.svn-base
Normal file
59
src/.svn/text-base/debug.c.svn-base
Normal file
@@ -0,0 +1,59 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
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
|
||||
``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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* General debugging routines */
|
||||
|
||||
void ffi_stop_here(void)
|
||||
{
|
||||
/* This function is only useful for debugging purposes.
|
||||
Place a breakpoint on ffi_stop_here to be notified of
|
||||
significant events. */
|
||||
}
|
||||
|
||||
/* This function should only be called via the FFI_ASSERT() macro */
|
||||
|
||||
void ffi_assert(char *expr, char *file, int line)
|
||||
{
|
||||
fprintf(stderr, "ASSERTION FAILURE: %s at %s:%d\n", expr, file, line);
|
||||
ffi_stop_here();
|
||||
abort();
|
||||
}
|
||||
|
||||
/* Perform a sanity check on an ffi_type structure */
|
||||
|
||||
void ffi_type_test(ffi_type *a, char *file, int line)
|
||||
{
|
||||
FFI_ASSERT_AT(a != NULL, file, line);
|
||||
|
||||
FFI_ASSERT_AT(a->type <= FFI_TYPE_LAST, file, line);
|
||||
FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->size > 0, file, line);
|
||||
FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->alignment > 0, file, line);
|
||||
FFI_ASSERT_AT(a->type != FFI_TYPE_STRUCT || a->elements != NULL, file, line);
|
||||
|
||||
}
|
||||
5099
src/.svn/text-base/dlmalloc.c.svn-base
Normal file
5099
src/.svn/text-base/dlmalloc.c.svn-base
Normal file
File diff suppressed because it is too large
Load Diff
356
src/.svn/text-base/java_raw_api.c.svn-base
Normal file
356
src/.svn/text-base/java_raw_api.c.svn-base
Normal file
@@ -0,0 +1,356 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
java_raw_api.c - Copyright (c) 1999, 2007, 2008 Red Hat, Inc.
|
||||
|
||||
Cloned from raw_api.c
|
||||
|
||||
Raw_api.c author: Kresten Krab Thorup <krab@gnu.org>
|
||||
Java_raw_api.c author: Hans-J. Boehm <hboehm@hpl.hp.com>
|
||||
|
||||
$Id $
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
/* This defines a Java- and 64-bit specific variant of the raw API. */
|
||||
/* It assumes that "raw" argument blocks look like Java stacks on a */
|
||||
/* 64-bit machine. Arguments that can be stored in a single stack */
|
||||
/* stack slots (longs, doubles) occupy 128 bits, but only the first */
|
||||
/* 64 bits are actually used. */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if !defined(NO_JAVA_RAW_API) && !defined(FFI_NO_RAW_API)
|
||||
|
||||
size_t
|
||||
ffi_java_raw_size (ffi_cif *cif)
|
||||
{
|
||||
size_t result = 0;
|
||||
int i;
|
||||
|
||||
ffi_type **at = cif->arg_types;
|
||||
|
||||
for (i = cif->nargs-1; i >= 0; i--, at++)
|
||||
{
|
||||
switch((*at) -> type) {
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
result += 2 * FFI_SIZEOF_JAVA_RAW;
|
||||
break;
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* No structure parameters in Java. */
|
||||
abort();
|
||||
default:
|
||||
result += FFI_SIZEOF_JAVA_RAW;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args)
|
||||
{
|
||||
unsigned i;
|
||||
ffi_type **tp = cif->arg_types;
|
||||
|
||||
#if WORDS_BIGENDIAN
|
||||
|
||||
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
||||
{
|
||||
switch ((*tp)->type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_SINT8:
|
||||
*args = (void*) ((char*)(raw++) + 3);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT16:
|
||||
*args = (void*) ((char*)(raw++) + 2);
|
||||
break;
|
||||
|
||||
#if FFI_SIZEOF_JAVA_RAW == 8
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
*args = (void *)raw;
|
||||
raw += 2;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
*args = (void*) &(raw++)->ptr;
|
||||
break;
|
||||
|
||||
default:
|
||||
*args = raw;
|
||||
raw +=
|
||||
ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
|
||||
}
|
||||
}
|
||||
|
||||
#else /* WORDS_BIGENDIAN */
|
||||
|
||||
#if !PDP
|
||||
|
||||
/* then assume little endian */
|
||||
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
||||
{
|
||||
#if FFI_SIZEOF_JAVA_RAW == 8
|
||||
switch((*tp)->type) {
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
*args = (void*) raw;
|
||||
raw += 2;
|
||||
break;
|
||||
default:
|
||||
*args = (void*) raw++;
|
||||
}
|
||||
#else /* FFI_SIZEOF_JAVA_RAW != 8 */
|
||||
*args = (void*) raw;
|
||||
raw +=
|
||||
ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
|
||||
#endif /* FFI_SIZEOF_JAVA_RAW == 8 */
|
||||
}
|
||||
|
||||
#else
|
||||
#error "pdp endian not supported"
|
||||
#endif /* ! PDP */
|
||||
|
||||
#endif /* WORDS_BIGENDIAN */
|
||||
}
|
||||
|
||||
void
|
||||
ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw)
|
||||
{
|
||||
unsigned i;
|
||||
ffi_type **tp = cif->arg_types;
|
||||
|
||||
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
||||
{
|
||||
switch ((*tp)->type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
#if WORDS_BIGENDIAN
|
||||
*(UINT32*)(raw++) = *(UINT8*) (*args);
|
||||
#else
|
||||
(raw++)->uint = *(UINT8*) (*args);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT8:
|
||||
#if WORDS_BIGENDIAN
|
||||
*(SINT32*)(raw++) = *(SINT8*) (*args);
|
||||
#else
|
||||
(raw++)->sint = *(SINT8*) (*args);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
#if WORDS_BIGENDIAN
|
||||
*(UINT32*)(raw++) = *(UINT16*) (*args);
|
||||
#else
|
||||
(raw++)->uint = *(UINT16*) (*args);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
#if WORDS_BIGENDIAN
|
||||
*(SINT32*)(raw++) = *(SINT16*) (*args);
|
||||
#else
|
||||
(raw++)->sint = *(SINT16*) (*args);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
#if WORDS_BIGENDIAN
|
||||
*(UINT32*)(raw++) = *(UINT32*) (*args);
|
||||
#else
|
||||
(raw++)->uint = *(UINT32*) (*args);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
#if WORDS_BIGENDIAN
|
||||
*(SINT32*)(raw++) = *(SINT32*) (*args);
|
||||
#else
|
||||
(raw++)->sint = *(SINT32*) (*args);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
(raw++)->flt = *(FLOAT32*) (*args);
|
||||
break;
|
||||
|
||||
#if FFI_SIZEOF_JAVA_RAW == 8
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
raw->uint = *(UINT64*) (*args);
|
||||
raw += 2;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
(raw++)->ptr = **(void***) args;
|
||||
break;
|
||||
|
||||
default:
|
||||
#if FFI_SIZEOF_JAVA_RAW == 8
|
||||
FFI_ASSERT(0); /* Should have covered all cases */
|
||||
#else
|
||||
memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
|
||||
raw +=
|
||||
ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !FFI_NATIVE_RAW_API
|
||||
|
||||
static void
|
||||
ffi_java_rvalue_to_raw (ffi_cif *cif, void *rvalue)
|
||||
{
|
||||
#if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_UINT32:
|
||||
*(UINT64 *)rvalue <<= 32;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_INT:
|
||||
#if FFI_SIZEOF_JAVA_RAW == 4
|
||||
case FFI_TYPE_POINTER:
|
||||
#endif
|
||||
*(SINT64 *)rvalue <<= 32;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
ffi_java_raw_to_rvalue (ffi_cif *cif, void *rvalue)
|
||||
{
|
||||
#if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_UINT32:
|
||||
*(UINT64 *)rvalue >>= 32;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_INT:
|
||||
*(SINT64 *)rvalue >>= 32;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This is a generic definition of ffi_raw_call, to be used if the
|
||||
* native system does not provide a machine-specific implementation.
|
||||
* Having this, allows code to be written for the raw API, without
|
||||
* the need for system-specific code to handle input in that format;
|
||||
* these following couple of functions will handle the translation forth
|
||||
* and back automatically. */
|
||||
|
||||
void ffi_java_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue,
|
||||
ffi_java_raw *raw)
|
||||
{
|
||||
void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
|
||||
ffi_java_raw_to_ptrarray (cif, raw, avalue);
|
||||
ffi_call (cif, fn, rvalue, avalue);
|
||||
ffi_java_rvalue_to_raw (cif, rvalue);
|
||||
}
|
||||
|
||||
#if FFI_CLOSURES /* base system provides closures */
|
||||
|
||||
static void
|
||||
ffi_java_translate_args (ffi_cif *cif, void *rvalue,
|
||||
void **avalue, void *user_data)
|
||||
{
|
||||
ffi_java_raw *raw = (ffi_java_raw*)alloca (ffi_java_raw_size (cif));
|
||||
ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
|
||||
|
||||
ffi_java_ptrarray_to_raw (cif, avalue, raw);
|
||||
(*cl->fun) (cif, rvalue, raw, cl->user_data);
|
||||
ffi_java_raw_to_rvalue (cif, rvalue);
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_java_raw_closure_loc (ffi_java_raw_closure* cl,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
ffi_status status;
|
||||
|
||||
status = ffi_prep_closure_loc ((ffi_closure*) cl,
|
||||
cif,
|
||||
&ffi_java_translate_args,
|
||||
codeloc,
|
||||
codeloc);
|
||||
if (status == FFI_OK)
|
||||
{
|
||||
cl->fun = fun;
|
||||
cl->user_data = user_data;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Again, here is the generic version of ffi_prep_raw_closure, which
|
||||
* will install an intermediate "hub" for translation of arguments from
|
||||
* the pointer-array format, to the raw format */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_java_raw_closure (ffi_java_raw_closure* cl,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
|
||||
void *user_data)
|
||||
{
|
||||
return ffi_prep_java_raw_closure_loc (cl, cif, fun, user_data, cl);
|
||||
}
|
||||
|
||||
#endif /* FFI_CLOSURES */
|
||||
#endif /* !FFI_NATIVE_RAW_API */
|
||||
#endif /* !FFI_NO_RAW_API */
|
||||
174
src/.svn/text-base/prep_cif.c.svn-base
Normal file
174
src/.svn/text-base/prep_cif.c.svn-base
Normal file
@@ -0,0 +1,174 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
prep_cif.c - Copyright (c) 1996, 1998, 2007 Red Hat, Inc.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Round up to FFI_SIZEOF_ARG. */
|
||||
|
||||
#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
|
||||
|
||||
/* Perform machine independent initialization of aggregate type
|
||||
specifications. */
|
||||
|
||||
static ffi_status initialize_aggregate(ffi_type *arg)
|
||||
{
|
||||
ffi_type **ptr;
|
||||
|
||||
FFI_ASSERT(arg != NULL);
|
||||
|
||||
FFI_ASSERT(arg->elements != NULL);
|
||||
FFI_ASSERT(arg->size == 0);
|
||||
FFI_ASSERT(arg->alignment == 0);
|
||||
|
||||
ptr = &(arg->elements[0]);
|
||||
|
||||
while ((*ptr) != NULL)
|
||||
{
|
||||
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
/* Perform a sanity check on the argument type */
|
||||
FFI_ASSERT_VALID_TYPE(*ptr);
|
||||
|
||||
arg->size = ALIGN(arg->size, (*ptr)->alignment);
|
||||
arg->size += (*ptr)->size;
|
||||
|
||||
arg->alignment = (arg->alignment > (*ptr)->alignment) ?
|
||||
arg->alignment : (*ptr)->alignment;
|
||||
|
||||
ptr++;
|
||||
}
|
||||
|
||||
/* Structure size includes tail padding. This is important for
|
||||
structures that fit in one register on ABIs like the PowerPC64
|
||||
Linux ABI that right justify small structs in a register.
|
||||
It's also needed for nested structure layout, for example
|
||||
struct A { long a; char b; }; struct B { struct A x; char y; };
|
||||
should find y at an offset of 2*sizeof(long) and result in a
|
||||
total size of 3*sizeof(long). */
|
||||
arg->size = ALIGN (arg->size, arg->alignment);
|
||||
|
||||
if (arg->size == 0)
|
||||
return FFI_BAD_TYPEDEF;
|
||||
else
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
#ifndef __CRIS__
|
||||
/* The CRIS ABI specifies structure elements to have byte
|
||||
alignment only, so it completely overrides this functions,
|
||||
which assumes "natural" alignment and padding. */
|
||||
|
||||
/* Perform machine independent ffi_cif preparation, then call
|
||||
machine dependent routine. */
|
||||
|
||||
ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
|
||||
ffi_type *rtype, ffi_type **atypes)
|
||||
{
|
||||
unsigned bytes = 0;
|
||||
unsigned int i;
|
||||
ffi_type **ptr;
|
||||
|
||||
FFI_ASSERT(cif != NULL);
|
||||
FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
|
||||
|
||||
cif->abi = abi;
|
||||
cif->arg_types = atypes;
|
||||
cif->nargs = nargs;
|
||||
cif->rtype = rtype;
|
||||
|
||||
cif->flags = 0;
|
||||
|
||||
/* Initialize the return type if necessary */
|
||||
if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
/* Perform a sanity check on the return type */
|
||||
FFI_ASSERT_VALID_TYPE(cif->rtype);
|
||||
|
||||
/* x86-64 and s390 stack space allocation is handled in prep_machdep. */
|
||||
#if !defined M68K && !defined __x86_64__ && !defined S390 && !defined PA
|
||||
/* Make space for the return structure pointer */
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT
|
||||
#ifdef SPARC
|
||||
&& (cif->abi != FFI_V9 || cif->rtype->size > 32)
|
||||
#endif
|
||||
#ifdef X86_DARWIN
|
||||
&& (cif->rtype->size > 8)
|
||||
#endif
|
||||
)
|
||||
bytes = STACK_ARG_SIZE(sizeof(void*));
|
||||
#endif
|
||||
|
||||
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
||||
{
|
||||
|
||||
/* Initialize any uninitialized aggregate type definitions */
|
||||
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
/* Perform a sanity check on the argument type, do this
|
||||
check after the initialization. */
|
||||
FFI_ASSERT_VALID_TYPE(*ptr);
|
||||
|
||||
#if !defined __x86_64__ && !defined S390 && !defined PA
|
||||
#ifdef SPARC
|
||||
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
|
||||
{
|
||||
/* Add any padding if necessary */
|
||||
if (((*ptr)->alignment - 1) & bytes)
|
||||
bytes = ALIGN(bytes, (*ptr)->alignment);
|
||||
|
||||
bytes += STACK_ARG_SIZE((*ptr)->size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
cif->bytes = bytes;
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
return ffi_prep_cif_machdep(cif);
|
||||
}
|
||||
#endif /* not __CRIS__ */
|
||||
|
||||
#if FFI_CLOSURES
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data)
|
||||
{
|
||||
return ffi_prep_closure_loc (closure, cif, fun, user_data, closure);
|
||||
}
|
||||
|
||||
#endif
|
||||
254
src/.svn/text-base/raw_api.c.svn-base
Normal file
254
src/.svn/text-base/raw_api.c.svn-base
Normal file
@@ -0,0 +1,254 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
raw_api.c - Copyright (c) 1999, 2008 Red Hat, Inc.
|
||||
|
||||
Author: Kresten Krab Thorup <krab@gnu.org>
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
/* This file defines generic functions for use with the raw api. */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#if !FFI_NO_RAW_API
|
||||
|
||||
size_t
|
||||
ffi_raw_size (ffi_cif *cif)
|
||||
{
|
||||
size_t result = 0;
|
||||
int i;
|
||||
|
||||
ffi_type **at = cif->arg_types;
|
||||
|
||||
for (i = cif->nargs-1; i >= 0; i--, at++)
|
||||
{
|
||||
#if !FFI_NO_STRUCTS
|
||||
if ((*at)->type == FFI_TYPE_STRUCT)
|
||||
result += ALIGN (sizeof (void*), FFI_SIZEOF_ARG);
|
||||
else
|
||||
#endif
|
||||
result += ALIGN ((*at)->size, FFI_SIZEOF_ARG);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
|
||||
{
|
||||
unsigned i;
|
||||
ffi_type **tp = cif->arg_types;
|
||||
|
||||
#if WORDS_BIGENDIAN
|
||||
|
||||
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
||||
{
|
||||
switch ((*tp)->type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_SINT8:
|
||||
*args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 1);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT16:
|
||||
*args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 2);
|
||||
break;
|
||||
|
||||
#if FFI_SIZEOF_ARG >= 4
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
*args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 4);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if !FFI_NO_STRUCTS
|
||||
case FFI_TYPE_STRUCT:
|
||||
*args = (raw++)->ptr;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
*args = (void*) &(raw++)->ptr;
|
||||
break;
|
||||
|
||||
default:
|
||||
*args = raw;
|
||||
raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
#else /* WORDS_BIGENDIAN */
|
||||
|
||||
#if !PDP
|
||||
|
||||
/* then assume little endian */
|
||||
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
||||
{
|
||||
#if !FFI_NO_STRUCTS
|
||||
if ((*tp)->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
*args = (raw++)->ptr;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
*args = (void*) raw;
|
||||
raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#error "pdp endian not supported"
|
||||
#endif /* ! PDP */
|
||||
|
||||
#endif /* WORDS_BIGENDIAN */
|
||||
}
|
||||
|
||||
void
|
||||
ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
|
||||
{
|
||||
unsigned i;
|
||||
ffi_type **tp = cif->arg_types;
|
||||
|
||||
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
||||
{
|
||||
switch ((*tp)->type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
(raw++)->uint = *(UINT8*) (*args);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT8:
|
||||
(raw++)->sint = *(SINT8*) (*args);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
(raw++)->uint = *(UINT16*) (*args);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
(raw++)->sint = *(SINT16*) (*args);
|
||||
break;
|
||||
|
||||
#if FFI_SIZEOF_ARG >= 4
|
||||
case FFI_TYPE_UINT32:
|
||||
(raw++)->uint = *(UINT32*) (*args);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
(raw++)->sint = *(SINT32*) (*args);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if !FFI_NO_STRUCTS
|
||||
case FFI_TYPE_STRUCT:
|
||||
(raw++)->ptr = *args;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
(raw++)->ptr = **(void***) args;
|
||||
break;
|
||||
|
||||
default:
|
||||
memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
|
||||
raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !FFI_NATIVE_RAW_API
|
||||
|
||||
|
||||
/* This is a generic definition of ffi_raw_call, to be used if the
|
||||
* native system does not provide a machine-specific implementation.
|
||||
* Having this, allows code to be written for the raw API, without
|
||||
* the need for system-specific code to handle input in that format;
|
||||
* these following couple of functions will handle the translation forth
|
||||
* and back automatically. */
|
||||
|
||||
void ffi_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *raw)
|
||||
{
|
||||
void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
|
||||
ffi_raw_to_ptrarray (cif, raw, avalue);
|
||||
ffi_call (cif, fn, rvalue, avalue);
|
||||
}
|
||||
|
||||
#if FFI_CLOSURES /* base system provides closures */
|
||||
|
||||
static void
|
||||
ffi_translate_args (ffi_cif *cif, void *rvalue,
|
||||
void **avalue, void *user_data)
|
||||
{
|
||||
ffi_raw *raw = (ffi_raw*)alloca (ffi_raw_size (cif));
|
||||
ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
|
||||
|
||||
ffi_ptrarray_to_raw (cif, avalue, raw);
|
||||
(*cl->fun) (cif, rvalue, raw, cl->user_data);
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_raw_closure_loc (ffi_raw_closure* cl,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
ffi_status status;
|
||||
|
||||
status = ffi_prep_closure_loc ((ffi_closure*) cl,
|
||||
cif,
|
||||
&ffi_translate_args,
|
||||
codeloc,
|
||||
codeloc);
|
||||
if (status == FFI_OK)
|
||||
{
|
||||
cl->fun = fun;
|
||||
cl->user_data = user_data;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif /* FFI_CLOSURES */
|
||||
#endif /* !FFI_NATIVE_RAW_API */
|
||||
|
||||
#if FFI_CLOSURES
|
||||
|
||||
/* Again, here is the generic version of ffi_prep_raw_closure, which
|
||||
* will install an intermediate "hub" for translation of arguments from
|
||||
* the pointer-array format, to the raw format */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_raw_closure (ffi_raw_closure* cl,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void *user_data)
|
||||
{
|
||||
return ffi_prep_raw_closure_loc (cl, cif, fun, user_data, cl);
|
||||
}
|
||||
|
||||
#endif /* FFI_CLOSURES */
|
||||
|
||||
#endif /* !FFI_NO_RAW_API */
|
||||
77
src/.svn/text-base/types.c.svn-base
Normal file
77
src/.svn/text-base/types.c.svn-base
Normal file
@@ -0,0 +1,77 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
types.c - Copyright (c) 1996, 1998 Red Hat, Inc.
|
||||
|
||||
Predefined ffi_types needed by libffi.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
/* Hide the basic type definitions from the header file, so that we
|
||||
can redefine them here as "const". */
|
||||
#define LIBFFI_HIDE_BASIC_TYPES
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
/* Type definitions */
|
||||
|
||||
#define FFI_TYPEDEF(name, type, id) \
|
||||
struct struct_align_##name { \
|
||||
char c; \
|
||||
type x; \
|
||||
}; \
|
||||
const ffi_type ffi_type_##name = { \
|
||||
sizeof(type), \
|
||||
offsetof(struct struct_align_##name, x), \
|
||||
id, NULL \
|
||||
}
|
||||
|
||||
/* Size and alignment are fake here. They must not be 0. */
|
||||
const ffi_type ffi_type_void = {
|
||||
1, 1, FFI_TYPE_VOID, NULL
|
||||
};
|
||||
|
||||
FFI_TYPEDEF(uint8, UINT8, FFI_TYPE_UINT8);
|
||||
FFI_TYPEDEF(sint8, SINT8, FFI_TYPE_SINT8);
|
||||
FFI_TYPEDEF(uint16, UINT16, FFI_TYPE_UINT16);
|
||||
FFI_TYPEDEF(sint16, SINT16, FFI_TYPE_SINT16);
|
||||
FFI_TYPEDEF(uint32, UINT32, FFI_TYPE_UINT32);
|
||||
FFI_TYPEDEF(sint32, SINT32, FFI_TYPE_SINT32);
|
||||
FFI_TYPEDEF(uint64, UINT64, FFI_TYPE_UINT64);
|
||||
FFI_TYPEDEF(sint64, SINT64, FFI_TYPE_SINT64);
|
||||
|
||||
FFI_TYPEDEF(pointer, void*, FFI_TYPE_POINTER);
|
||||
|
||||
FFI_TYPEDEF(float, float, FFI_TYPE_FLOAT);
|
||||
FFI_TYPEDEF(double, double, FFI_TYPE_DOUBLE);
|
||||
|
||||
#ifdef __alpha__
|
||||
/* Even if we're not configured to default to 128-bit long double,
|
||||
maintain binary compatibility, as -mlong-double-128 can be used
|
||||
at any time. */
|
||||
/* Validate the hard-coded number below. */
|
||||
# if defined(__LONG_DOUBLE_128__) && FFI_TYPE_LONGDOUBLE != 4
|
||||
# error FFI_TYPE_LONGDOUBLE out of date
|
||||
# endif
|
||||
const ffi_type ffi_type_longdouble = { 16, 16, 4, NULL };
|
||||
#elif FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
FFI_TYPEDEF(longdouble, long double, FFI_TYPE_LONGDOUBLE);
|
||||
#endif
|
||||
130
src/alpha/.svn/entries
Normal file
130
src/alpha/.svn/entries
Normal file
@@ -0,0 +1,130 @@
|
||||
10
|
||||
|
||||
dir
|
||||
152280
|
||||
svn://gcc.gnu.org/svn/gcc/trunk/libffi/src/alpha
|
||||
svn://gcc.gnu.org/svn/gcc
|
||||
|
||||
|
||||
|
||||
2009-06-04T15:43:03.499507Z
|
||||
148172
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
138bc75d-0d04-0410-961f-82ee72b054a4
|
||||
|
||||
ffitarget.h
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:01.000000Z
|
||||
d8ebc1ade0e8f0fa0cd86048ad927b6c
|
||||
2009-06-04T15:11:12.475454Z
|
||||
148171
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1771
|
||||
|
||||
ffi.c
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:01.000000Z
|
||||
6c0cd4327058ec8585b09041f1501c2c
|
||||
2009-06-04T15:43:03.499507Z
|
||||
148172
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
7379
|
||||
|
||||
osf.S
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:01.000000Z
|
||||
1c2284340e3ec316407056831adf7780
|
||||
2009-06-04T15:43:03.499507Z
|
||||
148172
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
7792
|
||||
|
||||
284
src/alpha/.svn/text-base/ffi.c.svn-base
Normal file
284
src/alpha/.svn/text-base/ffi.c.svn-base
Normal file
@@ -0,0 +1,284 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1998, 2001, 2007, 2008 Red Hat, Inc.
|
||||
|
||||
Alpha 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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
|
||||
all further uses in this file will refer to the 128-bit type. */
|
||||
#if defined(__LONG_DOUBLE_128__)
|
||||
# if FFI_TYPE_LONGDOUBLE != 4
|
||||
# error FFI_TYPE_LONGDOUBLE out of date
|
||||
# endif
|
||||
#else
|
||||
# undef FFI_TYPE_LONGDOUBLE
|
||||
# define FFI_TYPE_LONGDOUBLE 4
|
||||
#endif
|
||||
|
||||
extern void ffi_call_osf(void *, unsigned long, unsigned, void *, void (*)(void))
|
||||
FFI_HIDDEN;
|
||||
extern void ffi_closure_osf(void) FFI_HIDDEN;
|
||||
|
||||
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
/* Adjust cif->bytes to represent a minimum 6 words for the temporary
|
||||
register argument loading area. */
|
||||
if (cif->bytes < 6*FFI_SIZEOF_ARG)
|
||||
cif->bytes = 6*FFI_SIZEOF_ARG;
|
||||
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_STRUCT:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags = cif->rtype->type;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* 128-bit long double is returned in memory, like a struct. */
|
||||
cif->flags = FFI_TYPE_STRUCT;
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
unsigned long *stack, *argp;
|
||||
long i, avn;
|
||||
ffi_type **arg_types;
|
||||
|
||||
/* 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->flags == FFI_TYPE_STRUCT)
|
||||
rvalue = alloca(cif->rtype->size);
|
||||
|
||||
/* Allocate the space for the arguments, plus 4 words of temp
|
||||
space for ffi_call_osf. */
|
||||
argp = stack = alloca(cif->bytes + 4*FFI_SIZEOF_ARG);
|
||||
|
||||
if (cif->flags == FFI_TYPE_STRUCT)
|
||||
*(void **) argp++ = rvalue;
|
||||
|
||||
i = 0;
|
||||
avn = cif->nargs;
|
||||
arg_types = cif->arg_types;
|
||||
|
||||
while (i < avn)
|
||||
{
|
||||
size_t size = (*arg_types)->size;
|
||||
|
||||
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_LONGDOUBLE:
|
||||
/* 128-bit long double is passed by reference. */
|
||||
*(long double **) argp = (long double *)(* avalue);
|
||||
size = sizeof (long double *);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
memcpy(argp, *avalue, (*arg_types)->size);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
|
||||
argp += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
i++, arg_types++, avalue++;
|
||||
}
|
||||
|
||||
ffi_call_osf(stack, cif->bytes, cif->flags, rvalue, fn);
|
||||
}
|
||||
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
unsigned int *tramp;
|
||||
|
||||
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.
|
||||
|
||||
Tru64 UNIX as doesn't understand the imb mnemonic, so use call_pal
|
||||
instead, since both Compaq as and gas can handle it.
|
||||
|
||||
0x86 is PAL_imb in Tru64 UNIX <alpha/pal.h>. */
|
||||
asm volatile ("call_pal 0x86" : : : "memory");
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
|
||||
long FFI_HIDDEN
|
||||
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)
|
||||
{
|
||||
size_t size = arg_types[i]->size;
|
||||
|
||||
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;
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* 128-bit long double is passed by reference. */
|
||||
avalue[i] = (long double *) argp[argn];
|
||||
size = sizeof (long double *);
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
||||
argn += ALIGN(size, FFI_SIZEOF_ARG) / FFI_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;
|
||||
}
|
||||
48
src/alpha/.svn/text-base/ffitarget.h.svn-base
Normal file
48
src/alpha/.svn/text-base/ffitarget.h.svn-base
Normal file
@@ -0,0 +1,48 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for Alpha.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_OSF,
|
||||
FFI_LAST_ABI,
|
||||
FFI_DEFAULT_ABI = FFI_OSF
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 24
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
366
src/alpha/.svn/text-base/osf.S.svn-base
Normal file
366
src/alpha/.svn/text-base/osf.S.svn-base
Normal file
@@ -0,0 +1,366 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
osf.S - Copyright (c) 1998, 2001, 2007, 2008 Red Hat
|
||||
|
||||
Alpha/OSF 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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
.arch ev6
|
||||
.text
|
||||
|
||||
/* ffi_call_osf (void *args, unsigned long bytes, unsigned flags,
|
||||
void *raddr, void (*fnaddr)(void));
|
||||
|
||||
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_HIDDEN(ffi_call_osf)
|
||||
|
||||
ffi_call_osf:
|
||||
.frame $15, 32, $26, 0
|
||||
.mask 0x4008000, -32
|
||||
$LFB1:
|
||||
addq $16,$17,$1
|
||||
mov $16, $30
|
||||
stq $26, 0($1)
|
||||
stq $15, 8($1)
|
||||
stq $18, 16($1)
|
||||
mov $1, $15
|
||||
$LCFI1:
|
||||
.prologue 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 $21, 40($30)
|
||||
|
||||
# Deallocate the register argument area.
|
||||
lda $30, 48($30)
|
||||
|
||||
jsr $26, ($27), 0
|
||||
ldgp $29, 0($26)
|
||||
|
||||
# If the return value pointer is NULL, assume no return value.
|
||||
ldq $19, 24($15)
|
||||
ldq $18, 16($15)
|
||||
ldq $26, 0($15)
|
||||
$LCFI2:
|
||||
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
|
||||
|
||||
.align 3
|
||||
$noretval:
|
||||
ldq $15, 8($15)
|
||||
ret
|
||||
|
||||
.align 4
|
||||
$retint:
|
||||
stq $0, 0($19)
|
||||
nop
|
||||
ldq $15, 8($15)
|
||||
ret
|
||||
|
||||
.align 4
|
||||
$retfloat:
|
||||
sts $f0, 0($19)
|
||||
nop
|
||||
ldq $15, 8($15)
|
||||
ret
|
||||
|
||||
.align 4
|
||||
$retdouble:
|
||||
stt $f0, 0($19)
|
||||
nop
|
||||
ldq $15, 8($15)
|
||||
ret
|
||||
$LFE1:
|
||||
|
||||
.end ffi_call_osf
|
||||
|
||||
/* ffi_closure_osf(...)
|
||||
|
||||
Receives the closure argument in $1. */
|
||||
|
||||
.align 3
|
||||
.globl ffi_closure_osf
|
||||
.ent ffi_closure_osf
|
||||
FFI_HIDDEN(ffi_closure_osf)
|
||||
|
||||
ffi_closure_osf:
|
||||
.frame $30, 16*8, $26, 0
|
||||
.mask 0x4000000, -16*8
|
||||
$LFB2:
|
||||
ldgp $29, 0($27)
|
||||
subq $30, 16*8, $30
|
||||
$LCFI5:
|
||||
stq $26, 0($30)
|
||||
$LCFI6:
|
||||
.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
|
||||
$LFE2:
|
||||
|
||||
.end ffi_closure_osf
|
||||
|
||||
#ifdef __ELF__
|
||||
.section .rodata
|
||||
#else
|
||||
.rdata
|
||||
#endif
|
||||
$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_none # 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
|
||||
|
||||
#ifdef __ELF__
|
||||
.section .eh_frame,EH_FRAME_FLAGS,@progbits
|
||||
__FRAME_BEGIN__:
|
||||
.4byte $LECIE1-$LSCIE1 # Length of Common Information Entry
|
||||
$LSCIE1:
|
||||
.4byte 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.byte 0x1 # uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x78 # sleb128 -8; CIE Data Alignment Factor
|
||||
.byte 26 # CIE RA Column
|
||||
.byte 0x1 # uleb128 0x1; Augmentation size
|
||||
.byte 0x1b # FDE Encoding (pcrel sdata4)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.byte 30 # uleb128 column 30
|
||||
.byte 0 # uleb128 offset 0
|
||||
.align 3
|
||||
$LECIE1:
|
||||
$LSFDE1:
|
||||
.4byte $LEFDE1-$LASFDE1 # FDE Length
|
||||
$LASFDE1:
|
||||
.4byte $LASFDE1-__FRAME_BEGIN__ # FDE CIE offset
|
||||
.4byte $LFB1-. # FDE initial location
|
||||
.4byte $LFE1-$LFB1 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI1-$LFB1
|
||||
.byte 0x9a # DW_CFA_offset, column 26
|
||||
.byte 4 # uleb128 4*-8
|
||||
.byte 0x8f # DW_CFA_offset, column 15
|
||||
.byte 0x3 # uleb128 3*-8
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.byte 15 # uleb128 column 15
|
||||
.byte 32 # uleb128 offset 32
|
||||
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI2-$LCFI1
|
||||
.byte 0xda # DW_CFA_restore, column 26
|
||||
.align 3
|
||||
$LEFDE1:
|
||||
|
||||
$LSFDE3:
|
||||
.4byte $LEFDE3-$LASFDE3 # FDE Length
|
||||
$LASFDE3:
|
||||
.4byte $LASFDE3-__FRAME_BEGIN__ # FDE CIE offset
|
||||
.4byte $LFB2-. # FDE initial location
|
||||
.4byte $LFE2-$LFB2 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI5-$LFB2
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x80,0x1 # uleb128 128
|
||||
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI6-$LCFI5
|
||||
.byte 0x9a # DW_CFA_offset, column 26
|
||||
.byte 16 # uleb128 offset 16*-8
|
||||
.align 3
|
||||
$LEFDE3:
|
||||
|
||||
#ifdef __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
#endif
|
||||
284
src/alpha/ffi.c
Normal file
284
src/alpha/ffi.c
Normal file
@@ -0,0 +1,284 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1998, 2001, 2007, 2008 Red Hat, Inc.
|
||||
|
||||
Alpha 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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
|
||||
all further uses in this file will refer to the 128-bit type. */
|
||||
#if defined(__LONG_DOUBLE_128__)
|
||||
# if FFI_TYPE_LONGDOUBLE != 4
|
||||
# error FFI_TYPE_LONGDOUBLE out of date
|
||||
# endif
|
||||
#else
|
||||
# undef FFI_TYPE_LONGDOUBLE
|
||||
# define FFI_TYPE_LONGDOUBLE 4
|
||||
#endif
|
||||
|
||||
extern void ffi_call_osf(void *, unsigned long, unsigned, void *, void (*)(void))
|
||||
FFI_HIDDEN;
|
||||
extern void ffi_closure_osf(void) FFI_HIDDEN;
|
||||
|
||||
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
/* Adjust cif->bytes to represent a minimum 6 words for the temporary
|
||||
register argument loading area. */
|
||||
if (cif->bytes < 6*FFI_SIZEOF_ARG)
|
||||
cif->bytes = 6*FFI_SIZEOF_ARG;
|
||||
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_STRUCT:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags = cif->rtype->type;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* 128-bit long double is returned in memory, like a struct. */
|
||||
cif->flags = FFI_TYPE_STRUCT;
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
unsigned long *stack, *argp;
|
||||
long i, avn;
|
||||
ffi_type **arg_types;
|
||||
|
||||
/* 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->flags == FFI_TYPE_STRUCT)
|
||||
rvalue = alloca(cif->rtype->size);
|
||||
|
||||
/* Allocate the space for the arguments, plus 4 words of temp
|
||||
space for ffi_call_osf. */
|
||||
argp = stack = alloca(cif->bytes + 4*FFI_SIZEOF_ARG);
|
||||
|
||||
if (cif->flags == FFI_TYPE_STRUCT)
|
||||
*(void **) argp++ = rvalue;
|
||||
|
||||
i = 0;
|
||||
avn = cif->nargs;
|
||||
arg_types = cif->arg_types;
|
||||
|
||||
while (i < avn)
|
||||
{
|
||||
size_t size = (*arg_types)->size;
|
||||
|
||||
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_LONGDOUBLE:
|
||||
/* 128-bit long double is passed by reference. */
|
||||
*(long double **) argp = (long double *)(* avalue);
|
||||
size = sizeof (long double *);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
memcpy(argp, *avalue, (*arg_types)->size);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
|
||||
argp += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
i++, arg_types++, avalue++;
|
||||
}
|
||||
|
||||
ffi_call_osf(stack, cif->bytes, cif->flags, rvalue, fn);
|
||||
}
|
||||
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
unsigned int *tramp;
|
||||
|
||||
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.
|
||||
|
||||
Tru64 UNIX as doesn't understand the imb mnemonic, so use call_pal
|
||||
instead, since both Compaq as and gas can handle it.
|
||||
|
||||
0x86 is PAL_imb in Tru64 UNIX <alpha/pal.h>. */
|
||||
asm volatile ("call_pal 0x86" : : : "memory");
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
|
||||
long FFI_HIDDEN
|
||||
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)
|
||||
{
|
||||
size_t size = arg_types[i]->size;
|
||||
|
||||
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;
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* 128-bit long double is passed by reference. */
|
||||
avalue[i] = (long double *) argp[argn];
|
||||
size = sizeof (long double *);
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
||||
argn += ALIGN(size, FFI_SIZEOF_ARG) / FFI_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;
|
||||
}
|
||||
48
src/alpha/ffitarget.h
Normal file
48
src/alpha/ffitarget.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for Alpha.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_OSF,
|
||||
FFI_LAST_ABI,
|
||||
FFI_DEFAULT_ABI = FFI_OSF
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 24
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
366
src/alpha/osf.S
Normal file
366
src/alpha/osf.S
Normal file
@@ -0,0 +1,366 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
osf.S - Copyright (c) 1998, 2001, 2007, 2008 Red Hat
|
||||
|
||||
Alpha/OSF 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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
.arch ev6
|
||||
.text
|
||||
|
||||
/* ffi_call_osf (void *args, unsigned long bytes, unsigned flags,
|
||||
void *raddr, void (*fnaddr)(void));
|
||||
|
||||
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_HIDDEN(ffi_call_osf)
|
||||
|
||||
ffi_call_osf:
|
||||
.frame $15, 32, $26, 0
|
||||
.mask 0x4008000, -32
|
||||
$LFB1:
|
||||
addq $16,$17,$1
|
||||
mov $16, $30
|
||||
stq $26, 0($1)
|
||||
stq $15, 8($1)
|
||||
stq $18, 16($1)
|
||||
mov $1, $15
|
||||
$LCFI1:
|
||||
.prologue 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 $21, 40($30)
|
||||
|
||||
# Deallocate the register argument area.
|
||||
lda $30, 48($30)
|
||||
|
||||
jsr $26, ($27), 0
|
||||
ldgp $29, 0($26)
|
||||
|
||||
# If the return value pointer is NULL, assume no return value.
|
||||
ldq $19, 24($15)
|
||||
ldq $18, 16($15)
|
||||
ldq $26, 0($15)
|
||||
$LCFI2:
|
||||
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
|
||||
|
||||
.align 3
|
||||
$noretval:
|
||||
ldq $15, 8($15)
|
||||
ret
|
||||
|
||||
.align 4
|
||||
$retint:
|
||||
stq $0, 0($19)
|
||||
nop
|
||||
ldq $15, 8($15)
|
||||
ret
|
||||
|
||||
.align 4
|
||||
$retfloat:
|
||||
sts $f0, 0($19)
|
||||
nop
|
||||
ldq $15, 8($15)
|
||||
ret
|
||||
|
||||
.align 4
|
||||
$retdouble:
|
||||
stt $f0, 0($19)
|
||||
nop
|
||||
ldq $15, 8($15)
|
||||
ret
|
||||
$LFE1:
|
||||
|
||||
.end ffi_call_osf
|
||||
|
||||
/* ffi_closure_osf(...)
|
||||
|
||||
Receives the closure argument in $1. */
|
||||
|
||||
.align 3
|
||||
.globl ffi_closure_osf
|
||||
.ent ffi_closure_osf
|
||||
FFI_HIDDEN(ffi_closure_osf)
|
||||
|
||||
ffi_closure_osf:
|
||||
.frame $30, 16*8, $26, 0
|
||||
.mask 0x4000000, -16*8
|
||||
$LFB2:
|
||||
ldgp $29, 0($27)
|
||||
subq $30, 16*8, $30
|
||||
$LCFI5:
|
||||
stq $26, 0($30)
|
||||
$LCFI6:
|
||||
.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
|
||||
$LFE2:
|
||||
|
||||
.end ffi_closure_osf
|
||||
|
||||
#ifdef __ELF__
|
||||
.section .rodata
|
||||
#else
|
||||
.rdata
|
||||
#endif
|
||||
$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_none # 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
|
||||
|
||||
#ifdef __ELF__
|
||||
.section .eh_frame,EH_FRAME_FLAGS,@progbits
|
||||
__FRAME_BEGIN__:
|
||||
.4byte $LECIE1-$LSCIE1 # Length of Common Information Entry
|
||||
$LSCIE1:
|
||||
.4byte 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.byte 0x1 # uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x78 # sleb128 -8; CIE Data Alignment Factor
|
||||
.byte 26 # CIE RA Column
|
||||
.byte 0x1 # uleb128 0x1; Augmentation size
|
||||
.byte 0x1b # FDE Encoding (pcrel sdata4)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.byte 30 # uleb128 column 30
|
||||
.byte 0 # uleb128 offset 0
|
||||
.align 3
|
||||
$LECIE1:
|
||||
$LSFDE1:
|
||||
.4byte $LEFDE1-$LASFDE1 # FDE Length
|
||||
$LASFDE1:
|
||||
.4byte $LASFDE1-__FRAME_BEGIN__ # FDE CIE offset
|
||||
.4byte $LFB1-. # FDE initial location
|
||||
.4byte $LFE1-$LFB1 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI1-$LFB1
|
||||
.byte 0x9a # DW_CFA_offset, column 26
|
||||
.byte 4 # uleb128 4*-8
|
||||
.byte 0x8f # DW_CFA_offset, column 15
|
||||
.byte 0x3 # uleb128 3*-8
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.byte 15 # uleb128 column 15
|
||||
.byte 32 # uleb128 offset 32
|
||||
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI2-$LCFI1
|
||||
.byte 0xda # DW_CFA_restore, column 26
|
||||
.align 3
|
||||
$LEFDE1:
|
||||
|
||||
$LSFDE3:
|
||||
.4byte $LEFDE3-$LASFDE3 # FDE Length
|
||||
$LASFDE3:
|
||||
.4byte $LASFDE3-__FRAME_BEGIN__ # FDE CIE offset
|
||||
.4byte $LFB2-. # FDE initial location
|
||||
.4byte $LFE2-$LFB2 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI5-$LFB2
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x80,0x1 # uleb128 128
|
||||
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI6-$LCFI5
|
||||
.byte 0x9a # DW_CFA_offset, column 26
|
||||
.byte 16 # uleb128 offset 16*-8
|
||||
.align 3
|
||||
$LEFDE3:
|
||||
|
||||
#ifdef __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
#endif
|
||||
130
src/arm/.svn/entries
Normal file
130
src/arm/.svn/entries
Normal file
@@ -0,0 +1,130 @@
|
||||
10
|
||||
|
||||
dir
|
||||
152280
|
||||
svn://gcc.gnu.org/svn/gcc/trunk/libffi/src/arm
|
||||
svn://gcc.gnu.org/svn/gcc
|
||||
|
||||
|
||||
|
||||
2009-09-23T14:50:35.044390Z
|
||||
152075
|
||||
doko
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
138bc75d-0d04-0410-961f-82ee72b054a4
|
||||
|
||||
ffitarget.h
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:00.000000Z
|
||||
7d755bdfcc6115d45d2547cf7a149df4
|
||||
2009-06-04T15:11:12.475454Z
|
||||
148171
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1794
|
||||
|
||||
ffi.c
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:00.000000Z
|
||||
a0ee6e86ca97fcdd084efc21500ebccd
|
||||
2009-06-04T15:43:03.499507Z
|
||||
148172
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
7974
|
||||
|
||||
sysv.S
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-09-27T03:30:26.000000Z
|
||||
4d876a004cbf93486edab24a0c84a4d8
|
||||
2009-09-23T14:50:35.044390Z
|
||||
152075
|
||||
doko
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
6925
|
||||
|
||||
309
src/arm/.svn/text-base/ffi.c.svn-base
Normal file
309
src/arm/.svn/text-base/ffi.c.svn-base
Normal file
@@ -0,0 +1,309 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1998, 2008 Red Hat, Inc.
|
||||
|
||||
ARM 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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* 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)
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
|
||||
argp = stack;
|
||||
|
||||
if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
|
||||
*(void **) argp = ecif->rvalue;
|
||||
argp += 4;
|
||||
}
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
(i != 0);
|
||||
i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
/* Align if necessary */
|
||||
if (((*p_arg)->alignment - 1) & (unsigned) argp) {
|
||||
argp = (char *) ALIGN(argp, (*p_arg)->alignment);
|
||||
}
|
||||
|
||||
if ((*p_arg)->type == FFI_TYPE_STRUCT)
|
||||
argp = (char *) ALIGN(argp, 4);
|
||||
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof(int))
|
||||
{
|
||||
z = sizeof(int);
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
memcpy(argp, *p_argv, (*p_arg)->size);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
}
|
||||
else if (z == sizeof(int))
|
||||
{
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(argp, *p_argv, z);
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
/* Round the stack up to a multiple of 8 bytes. This isn't needed
|
||||
everywhere, but it is on some platforms, and it doesn't harm anything
|
||||
when it isn't needed. */
|
||||
cif->bytes = (cif->bytes + 7) & ~7;
|
||||
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
cif->flags = (unsigned) FFI_TYPE_SINT64;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
if (cif->rtype->size <= 4)
|
||||
/* A Composite Type not larger than 4 bytes is returned in r0. */
|
||||
cif->flags = (unsigned)FFI_TYPE_INT;
|
||||
else
|
||||
/* A Composite Type larger than 4 bytes, or whose size cannot
|
||||
be determined statically ... is stored in memory at an
|
||||
address passed [in r0]. */
|
||||
cif->flags = (unsigned)FFI_TYPE_STRUCT;
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
|
||||
unsigned, unsigned, unsigned *, void (*fn)(void));
|
||||
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
int small_struct = (cif->flags == FFI_TYPE_INT
|
||||
&& cif->rtype->type == FFI_TYPE_STRUCT);
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
unsigned int temp;
|
||||
|
||||
/* 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->flags == FFI_TYPE_STRUCT))
|
||||
{
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
}
|
||||
else if (small_struct)
|
||||
ecif.rvalue = &temp;
|
||||
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;
|
||||
}
|
||||
if (small_struct)
|
||||
memcpy (rvalue, &temp, cif->rtype->size);
|
||||
}
|
||||
|
||||
/** private members **/
|
||||
|
||||
static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
|
||||
void** args, ffi_cif* cif);
|
||||
|
||||
void ffi_closure_SYSV (ffi_closure *);
|
||||
|
||||
/* This function is jumped to by the trampoline */
|
||||
|
||||
unsigned int
|
||||
ffi_closure_SYSV_inner (closure, respp, args)
|
||||
ffi_closure *closure;
|
||||
void **respp;
|
||||
void *args;
|
||||
{
|
||||
// our various things...
|
||||
ffi_cif *cif;
|
||||
void **arg_area;
|
||||
|
||||
cif = closure->cif;
|
||||
arg_area = (void**) alloca (cif->nargs * sizeof (void*));
|
||||
|
||||
/* this call will initialize ARG_AREA, such that each
|
||||
* element in that array points to the corresponding
|
||||
* value on the stack; and if the function returns
|
||||
* a structure, it will re-set RESP to point to the
|
||||
* structure return address. */
|
||||
|
||||
ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
|
||||
|
||||
(closure->fun) (cif, *respp, arg_area, closure->user_data);
|
||||
|
||||
return cif->flags;
|
||||
}
|
||||
|
||||
/*@-exportheader@*/
|
||||
static void
|
||||
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
|
||||
void **avalue, ffi_cif *cif)
|
||||
/*@=exportheader@*/
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
|
||||
argp = stack;
|
||||
|
||||
if ( cif->flags == FFI_TYPE_STRUCT ) {
|
||||
*rvalue = *(void **) argp;
|
||||
argp += 4;
|
||||
}
|
||||
|
||||
p_argv = avalue;
|
||||
|
||||
for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
size_t alignment = (*p_arg)->alignment;
|
||||
if (alignment < 4)
|
||||
alignment = 4;
|
||||
/* Align if necessary */
|
||||
if ((alignment - 1) & (unsigned) argp) {
|
||||
argp = (char *) ALIGN(argp, alignment);
|
||||
}
|
||||
|
||||
z = (*p_arg)->size;
|
||||
|
||||
/* because we're little endian, this is what it turns into. */
|
||||
|
||||
*p_argv = (void*) argp;
|
||||
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* How to make a trampoline. */
|
||||
|
||||
#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
|
||||
({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
|
||||
unsigned int __fun = (unsigned int)(FUN); \
|
||||
unsigned int __ctx = (unsigned int)(CTX); \
|
||||
*(unsigned int*) &__tramp[0] = 0xe92d000f; /* stmfd sp!, {r0-r3} */ \
|
||||
*(unsigned int*) &__tramp[4] = 0xe59f0000; /* ldr r0, [pc] */ \
|
||||
*(unsigned int*) &__tramp[8] = 0xe59ff000; /* ldr pc, [pc] */ \
|
||||
*(unsigned int*) &__tramp[12] = __ctx; \
|
||||
*(unsigned int*) &__tramp[16] = __fun; \
|
||||
__clear_cache((&__tramp[0]), (&__tramp[19])); \
|
||||
})
|
||||
|
||||
|
||||
/* the cif must already be prep'ed */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
FFI_ASSERT (cif->abi == FFI_SYSV);
|
||||
|
||||
FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
|
||||
&ffi_closure_SYSV, \
|
||||
codeloc);
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
49
src/arm/.svn/text-base/ffitarget.h.svn-base
Normal file
49
src/arm/.svn/text-base/ffitarget.h.svn-base
Normal file
@@ -0,0 +1,49 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for ARM.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_SYSV,
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 20
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
|
||||
306
src/arm/.svn/text-base/sysv.S.svn-base
Normal file
306
src/arm/.svn/text-base/sysv.S.svn-base
Normal file
@@ -0,0 +1,306 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 1998, 2008 Red Hat, Inc.
|
||||
|
||||
ARM 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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#ifdef HAVE_MACHINE_ASM_H
|
||||
#include <machine/asm.h>
|
||||
#else
|
||||
#ifdef __USER_LABEL_PREFIX__
|
||||
#define CONCAT1(a, b) CONCAT2(a, b)
|
||||
#define CONCAT2(a, b) a ## b
|
||||
|
||||
/* Use the right prefix for global labels. */
|
||||
#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
|
||||
#else
|
||||
#define CNAME(x) x
|
||||
#endif
|
||||
#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
|
||||
#endif
|
||||
|
||||
#ifdef __ELF__
|
||||
#define LSYM(x) .x
|
||||
#else
|
||||
#define LSYM(x) x
|
||||
#endif
|
||||
|
||||
/* We need a better way of testing for this, but for now, this is all
|
||||
we can do. */
|
||||
@ This selects the minimum architecture level required.
|
||||
#define __ARM_ARCH__ 3
|
||||
|
||||
#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
|
||||
# undef __ARM_ARCH__
|
||||
# define __ARM_ARCH__ 4
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
|
||||
|| defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
|
||||
|| defined(__ARM_ARCH_5TEJ__)
|
||||
# undef __ARM_ARCH__
|
||||
# define __ARM_ARCH__ 5
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
|
||||
|| defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
|
||||
|| defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \
|
||||
|| defined(__ARM_ARCH_6M__)
|
||||
# undef __ARM_ARCH__
|
||||
# define __ARM_ARCH__ 6
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
|
||||
|| defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__)
|
||||
# undef __ARM_ARCH__
|
||||
# define __ARM_ARCH__ 7
|
||||
#endif
|
||||
|
||||
#if __ARM_ARCH__ >= 5
|
||||
# define call_reg(x) blx x
|
||||
#elif defined (__ARM_ARCH_4T__)
|
||||
# define call_reg(x) mov lr, pc ; bx x
|
||||
# if defined(__thumb__) || defined(__THUMB_INTERWORK__)
|
||||
# define __INTERWORKING__
|
||||
# endif
|
||||
#else
|
||||
# define call_reg(x) mov lr, pc ; mov pc, x
|
||||
#endif
|
||||
|
||||
/* Conditionally compile unwinder directives. */
|
||||
#ifdef __ARM_EABI__
|
||||
#define UNWIND
|
||||
#else
|
||||
#define UNWIND @
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
|
||||
.macro ARM_FUNC_START name
|
||||
.text
|
||||
.align 0
|
||||
.thumb
|
||||
.thumb_func
|
||||
ENTRY(\name)
|
||||
bx pc
|
||||
nop
|
||||
.arm
|
||||
UNWIND .fnstart
|
||||
/* A hook to tell gdb that we've switched to ARM mode. Also used to call
|
||||
directly from other local arm routines. */
|
||||
_L__\name:
|
||||
.endm
|
||||
#else
|
||||
.macro ARM_FUNC_START name
|
||||
.text
|
||||
.align 0
|
||||
.arm
|
||||
ENTRY(\name)
|
||||
UNWIND .fnstart
|
||||
.endm
|
||||
#endif
|
||||
|
||||
.macro RETLDM regs=, cond=, dirn=ia
|
||||
#if defined (__INTERWORKING__)
|
||||
.ifc "\regs",""
|
||||
ldr\cond lr, [sp], #4
|
||||
.else
|
||||
ldm\cond\dirn sp!, {\regs, lr}
|
||||
.endif
|
||||
bx\cond lr
|
||||
#else
|
||||
.ifc "\regs",""
|
||||
ldr\cond pc, [sp], #4
|
||||
.else
|
||||
ldm\cond\dirn sp!, {\regs, pc}
|
||||
.endif
|
||||
#endif
|
||||
.endm
|
||||
|
||||
|
||||
@ r0: ffi_prep_args
|
||||
@ r1: &ecif
|
||||
@ r2: cif->bytes
|
||||
@ r3: fig->flags
|
||||
@ sp+0: ecif.rvalue
|
||||
@ sp+4: fn
|
||||
|
||||
@ This assumes we are using gas.
|
||||
ARM_FUNC_START ffi_call_SYSV
|
||||
@ Save registers
|
||||
stmfd sp!, {r0-r3, fp, lr}
|
||||
UNWIND .save {r0-r3, fp, lr}
|
||||
mov fp, sp
|
||||
|
||||
UNWIND .setfp fp, sp
|
||||
|
||||
@ Make room for all of the new args.
|
||||
sub sp, fp, r2
|
||||
|
||||
@ Place all of the ffi_prep_args in position
|
||||
mov ip, r0
|
||||
mov r0, sp
|
||||
@ r1 already set
|
||||
|
||||
@ Call ffi_prep_args(stack, &ecif)
|
||||
call_reg(ip)
|
||||
|
||||
@ move first 4 parameters in registers
|
||||
ldmia sp, {r0-r3}
|
||||
|
||||
@ and adjust stack
|
||||
ldr ip, [fp, #8]
|
||||
cmp ip, #16
|
||||
movhs ip, #16
|
||||
add sp, sp, ip
|
||||
|
||||
@ call (fn) (...)
|
||||
ldr ip, [fp, #28]
|
||||
call_reg(ip)
|
||||
|
||||
@ Remove the space we pushed for the args
|
||||
mov sp, fp
|
||||
|
||||
@ Load r2 with the pointer to storage for the return value
|
||||
ldr r2, [sp, #24]
|
||||
|
||||
@ Load r3 with the return type code
|
||||
ldr r3, [sp, #12]
|
||||
|
||||
@ If the return value pointer is NULL, assume no return value.
|
||||
cmp r2, #0
|
||||
beq LSYM(Lepilogue)
|
||||
|
||||
@ return INT
|
||||
cmp r3, #FFI_TYPE_INT
|
||||
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
|
||||
cmpne r3, #FFI_TYPE_FLOAT
|
||||
#endif
|
||||
streq r0, [r2]
|
||||
beq LSYM(Lepilogue)
|
||||
|
||||
@ return INT64
|
||||
cmp r3, #FFI_TYPE_SINT64
|
||||
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
|
||||
cmpne r3, #FFI_TYPE_DOUBLE
|
||||
#endif
|
||||
stmeqia r2, {r0, r1}
|
||||
|
||||
#if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
|
||||
beq LSYM(Lepilogue)
|
||||
|
||||
@ return FLOAT
|
||||
cmp r3, #FFI_TYPE_FLOAT
|
||||
stfeqs f0, [r2]
|
||||
beq LSYM(Lepilogue)
|
||||
|
||||
@ return DOUBLE or LONGDOUBLE
|
||||
cmp r3, #FFI_TYPE_DOUBLE
|
||||
stfeqd f0, [r2]
|
||||
#endif
|
||||
|
||||
LSYM(Lepilogue):
|
||||
RETLDM "r0-r3,fp"
|
||||
|
||||
.ffi_call_SYSV_end:
|
||||
UNWIND .fnend
|
||||
.size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
|
||||
|
||||
/*
|
||||
unsigned int FFI_HIDDEN
|
||||
ffi_closure_SYSV_inner (closure, respp, args)
|
||||
ffi_closure *closure;
|
||||
void **respp;
|
||||
void *args;
|
||||
*/
|
||||
|
||||
ARM_FUNC_START ffi_closure_SYSV
|
||||
UNWIND .pad #16
|
||||
add ip, sp, #16
|
||||
stmfd sp!, {ip, lr}
|
||||
UNWIND .save {r0, lr}
|
||||
add r2, sp, #8
|
||||
.pad #16
|
||||
sub sp, sp, #16
|
||||
str sp, [sp, #8]
|
||||
add r1, sp, #8
|
||||
bl ffi_closure_SYSV_inner
|
||||
cmp r0, #FFI_TYPE_INT
|
||||
beq .Lretint
|
||||
|
||||
cmp r0, #FFI_TYPE_FLOAT
|
||||
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
|
||||
beq .Lretint
|
||||
#else
|
||||
beq .Lretfloat
|
||||
#endif
|
||||
|
||||
cmp r0, #FFI_TYPE_DOUBLE
|
||||
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
|
||||
beq .Lretlonglong
|
||||
#else
|
||||
beq .Lretdouble
|
||||
#endif
|
||||
|
||||
cmp r0, #FFI_TYPE_LONGDOUBLE
|
||||
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
|
||||
beq .Lretlonglong
|
||||
#else
|
||||
beq .Lretlongdouble
|
||||
#endif
|
||||
|
||||
cmp r0, #FFI_TYPE_SINT64
|
||||
beq .Lretlonglong
|
||||
.Lclosure_epilogue:
|
||||
add sp, sp, #16
|
||||
ldmfd sp, {sp, pc}
|
||||
.Lretint:
|
||||
ldr r0, [sp]
|
||||
b .Lclosure_epilogue
|
||||
.Lretlonglong:
|
||||
ldr r0, [sp]
|
||||
ldr r1, [sp, #4]
|
||||
b .Lclosure_epilogue
|
||||
|
||||
#if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
|
||||
.Lretfloat:
|
||||
ldfs f0, [sp]
|
||||
b .Lclosure_epilogue
|
||||
.Lretdouble:
|
||||
ldfd f0, [sp]
|
||||
b .Lclosure_epilogue
|
||||
.Lretlongdouble:
|
||||
ldfd f0, [sp]
|
||||
b .Lclosure_epilogue
|
||||
#endif
|
||||
|
||||
.ffi_closure_SYSV_end:
|
||||
UNWIND .fnend
|
||||
.size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
#endif
|
||||
309
src/arm/ffi.c
Normal file
309
src/arm/ffi.c
Normal file
@@ -0,0 +1,309 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1998, 2008 Red Hat, Inc.
|
||||
|
||||
ARM 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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* 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)
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
|
||||
argp = stack;
|
||||
|
||||
if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
|
||||
*(void **) argp = ecif->rvalue;
|
||||
argp += 4;
|
||||
}
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
(i != 0);
|
||||
i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
/* Align if necessary */
|
||||
if (((*p_arg)->alignment - 1) & (unsigned) argp) {
|
||||
argp = (char *) ALIGN(argp, (*p_arg)->alignment);
|
||||
}
|
||||
|
||||
if ((*p_arg)->type == FFI_TYPE_STRUCT)
|
||||
argp = (char *) ALIGN(argp, 4);
|
||||
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof(int))
|
||||
{
|
||||
z = sizeof(int);
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
memcpy(argp, *p_argv, (*p_arg)->size);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
}
|
||||
else if (z == sizeof(int))
|
||||
{
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(argp, *p_argv, z);
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
/* Round the stack up to a multiple of 8 bytes. This isn't needed
|
||||
everywhere, but it is on some platforms, and it doesn't harm anything
|
||||
when it isn't needed. */
|
||||
cif->bytes = (cif->bytes + 7) & ~7;
|
||||
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
cif->flags = (unsigned) FFI_TYPE_SINT64;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
if (cif->rtype->size <= 4)
|
||||
/* A Composite Type not larger than 4 bytes is returned in r0. */
|
||||
cif->flags = (unsigned)FFI_TYPE_INT;
|
||||
else
|
||||
/* A Composite Type larger than 4 bytes, or whose size cannot
|
||||
be determined statically ... is stored in memory at an
|
||||
address passed [in r0]. */
|
||||
cif->flags = (unsigned)FFI_TYPE_STRUCT;
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
|
||||
unsigned, unsigned, unsigned *, void (*fn)(void));
|
||||
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
int small_struct = (cif->flags == FFI_TYPE_INT
|
||||
&& cif->rtype->type == FFI_TYPE_STRUCT);
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
unsigned int temp;
|
||||
|
||||
/* 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->flags == FFI_TYPE_STRUCT))
|
||||
{
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
}
|
||||
else if (small_struct)
|
||||
ecif.rvalue = &temp;
|
||||
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;
|
||||
}
|
||||
if (small_struct)
|
||||
memcpy (rvalue, &temp, cif->rtype->size);
|
||||
}
|
||||
|
||||
/** private members **/
|
||||
|
||||
static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
|
||||
void** args, ffi_cif* cif);
|
||||
|
||||
void ffi_closure_SYSV (ffi_closure *);
|
||||
|
||||
/* This function is jumped to by the trampoline */
|
||||
|
||||
unsigned int
|
||||
ffi_closure_SYSV_inner (closure, respp, args)
|
||||
ffi_closure *closure;
|
||||
void **respp;
|
||||
void *args;
|
||||
{
|
||||
// our various things...
|
||||
ffi_cif *cif;
|
||||
void **arg_area;
|
||||
|
||||
cif = closure->cif;
|
||||
arg_area = (void**) alloca (cif->nargs * sizeof (void*));
|
||||
|
||||
/* this call will initialize ARG_AREA, such that each
|
||||
* element in that array points to the corresponding
|
||||
* value on the stack; and if the function returns
|
||||
* a structure, it will re-set RESP to point to the
|
||||
* structure return address. */
|
||||
|
||||
ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
|
||||
|
||||
(closure->fun) (cif, *respp, arg_area, closure->user_data);
|
||||
|
||||
return cif->flags;
|
||||
}
|
||||
|
||||
/*@-exportheader@*/
|
||||
static void
|
||||
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
|
||||
void **avalue, ffi_cif *cif)
|
||||
/*@=exportheader@*/
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
|
||||
argp = stack;
|
||||
|
||||
if ( cif->flags == FFI_TYPE_STRUCT ) {
|
||||
*rvalue = *(void **) argp;
|
||||
argp += 4;
|
||||
}
|
||||
|
||||
p_argv = avalue;
|
||||
|
||||
for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
size_t alignment = (*p_arg)->alignment;
|
||||
if (alignment < 4)
|
||||
alignment = 4;
|
||||
/* Align if necessary */
|
||||
if ((alignment - 1) & (unsigned) argp) {
|
||||
argp = (char *) ALIGN(argp, alignment);
|
||||
}
|
||||
|
||||
z = (*p_arg)->size;
|
||||
|
||||
/* because we're little endian, this is what it turns into. */
|
||||
|
||||
*p_argv = (void*) argp;
|
||||
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* How to make a trampoline. */
|
||||
|
||||
#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
|
||||
({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
|
||||
unsigned int __fun = (unsigned int)(FUN); \
|
||||
unsigned int __ctx = (unsigned int)(CTX); \
|
||||
*(unsigned int*) &__tramp[0] = 0xe92d000f; /* stmfd sp!, {r0-r3} */ \
|
||||
*(unsigned int*) &__tramp[4] = 0xe59f0000; /* ldr r0, [pc] */ \
|
||||
*(unsigned int*) &__tramp[8] = 0xe59ff000; /* ldr pc, [pc] */ \
|
||||
*(unsigned int*) &__tramp[12] = __ctx; \
|
||||
*(unsigned int*) &__tramp[16] = __fun; \
|
||||
__clear_cache((&__tramp[0]), (&__tramp[19])); \
|
||||
})
|
||||
|
||||
|
||||
/* the cif must already be prep'ed */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
FFI_ASSERT (cif->abi == FFI_SYSV);
|
||||
|
||||
FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
|
||||
&ffi_closure_SYSV, \
|
||||
codeloc);
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
49
src/arm/ffitarget.h
Normal file
49
src/arm/ffitarget.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for ARM.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_SYSV,
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 20
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
|
||||
306
src/arm/sysv.S
Normal file
306
src/arm/sysv.S
Normal file
@@ -0,0 +1,306 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 1998, 2008 Red Hat, Inc.
|
||||
|
||||
ARM 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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#ifdef HAVE_MACHINE_ASM_H
|
||||
#include <machine/asm.h>
|
||||
#else
|
||||
#ifdef __USER_LABEL_PREFIX__
|
||||
#define CONCAT1(a, b) CONCAT2(a, b)
|
||||
#define CONCAT2(a, b) a ## b
|
||||
|
||||
/* Use the right prefix for global labels. */
|
||||
#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
|
||||
#else
|
||||
#define CNAME(x) x
|
||||
#endif
|
||||
#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
|
||||
#endif
|
||||
|
||||
#ifdef __ELF__
|
||||
#define LSYM(x) .x
|
||||
#else
|
||||
#define LSYM(x) x
|
||||
#endif
|
||||
|
||||
/* We need a better way of testing for this, but for now, this is all
|
||||
we can do. */
|
||||
@ This selects the minimum architecture level required.
|
||||
#define __ARM_ARCH__ 3
|
||||
|
||||
#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
|
||||
# undef __ARM_ARCH__
|
||||
# define __ARM_ARCH__ 4
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
|
||||
|| defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
|
||||
|| defined(__ARM_ARCH_5TEJ__)
|
||||
# undef __ARM_ARCH__
|
||||
# define __ARM_ARCH__ 5
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
|
||||
|| defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
|
||||
|| defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \
|
||||
|| defined(__ARM_ARCH_6M__)
|
||||
# undef __ARM_ARCH__
|
||||
# define __ARM_ARCH__ 6
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
|
||||
|| defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__)
|
||||
# undef __ARM_ARCH__
|
||||
# define __ARM_ARCH__ 7
|
||||
#endif
|
||||
|
||||
#if __ARM_ARCH__ >= 5
|
||||
# define call_reg(x) blx x
|
||||
#elif defined (__ARM_ARCH_4T__)
|
||||
# define call_reg(x) mov lr, pc ; bx x
|
||||
# if defined(__thumb__) || defined(__THUMB_INTERWORK__)
|
||||
# define __INTERWORKING__
|
||||
# endif
|
||||
#else
|
||||
# define call_reg(x) mov lr, pc ; mov pc, x
|
||||
#endif
|
||||
|
||||
/* Conditionally compile unwinder directives. */
|
||||
#ifdef __ARM_EABI__
|
||||
#define UNWIND
|
||||
#else
|
||||
#define UNWIND @
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
|
||||
.macro ARM_FUNC_START name
|
||||
.text
|
||||
.align 0
|
||||
.thumb
|
||||
.thumb_func
|
||||
ENTRY(\name)
|
||||
bx pc
|
||||
nop
|
||||
.arm
|
||||
UNWIND .fnstart
|
||||
/* A hook to tell gdb that we've switched to ARM mode. Also used to call
|
||||
directly from other local arm routines. */
|
||||
_L__\name:
|
||||
.endm
|
||||
#else
|
||||
.macro ARM_FUNC_START name
|
||||
.text
|
||||
.align 0
|
||||
.arm
|
||||
ENTRY(\name)
|
||||
UNWIND .fnstart
|
||||
.endm
|
||||
#endif
|
||||
|
||||
.macro RETLDM regs=, cond=, dirn=ia
|
||||
#if defined (__INTERWORKING__)
|
||||
.ifc "\regs",""
|
||||
ldr\cond lr, [sp], #4
|
||||
.else
|
||||
ldm\cond\dirn sp!, {\regs, lr}
|
||||
.endif
|
||||
bx\cond lr
|
||||
#else
|
||||
.ifc "\regs",""
|
||||
ldr\cond pc, [sp], #4
|
||||
.else
|
||||
ldm\cond\dirn sp!, {\regs, pc}
|
||||
.endif
|
||||
#endif
|
||||
.endm
|
||||
|
||||
|
||||
@ r0: ffi_prep_args
|
||||
@ r1: &ecif
|
||||
@ r2: cif->bytes
|
||||
@ r3: fig->flags
|
||||
@ sp+0: ecif.rvalue
|
||||
@ sp+4: fn
|
||||
|
||||
@ This assumes we are using gas.
|
||||
ARM_FUNC_START ffi_call_SYSV
|
||||
@ Save registers
|
||||
stmfd sp!, {r0-r3, fp, lr}
|
||||
UNWIND .save {r0-r3, fp, lr}
|
||||
mov fp, sp
|
||||
|
||||
UNWIND .setfp fp, sp
|
||||
|
||||
@ Make room for all of the new args.
|
||||
sub sp, fp, r2
|
||||
|
||||
@ Place all of the ffi_prep_args in position
|
||||
mov ip, r0
|
||||
mov r0, sp
|
||||
@ r1 already set
|
||||
|
||||
@ Call ffi_prep_args(stack, &ecif)
|
||||
call_reg(ip)
|
||||
|
||||
@ move first 4 parameters in registers
|
||||
ldmia sp, {r0-r3}
|
||||
|
||||
@ and adjust stack
|
||||
ldr ip, [fp, #8]
|
||||
cmp ip, #16
|
||||
movhs ip, #16
|
||||
add sp, sp, ip
|
||||
|
||||
@ call (fn) (...)
|
||||
ldr ip, [fp, #28]
|
||||
call_reg(ip)
|
||||
|
||||
@ Remove the space we pushed for the args
|
||||
mov sp, fp
|
||||
|
||||
@ Load r2 with the pointer to storage for the return value
|
||||
ldr r2, [sp, #24]
|
||||
|
||||
@ Load r3 with the return type code
|
||||
ldr r3, [sp, #12]
|
||||
|
||||
@ If the return value pointer is NULL, assume no return value.
|
||||
cmp r2, #0
|
||||
beq LSYM(Lepilogue)
|
||||
|
||||
@ return INT
|
||||
cmp r3, #FFI_TYPE_INT
|
||||
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
|
||||
cmpne r3, #FFI_TYPE_FLOAT
|
||||
#endif
|
||||
streq r0, [r2]
|
||||
beq LSYM(Lepilogue)
|
||||
|
||||
@ return INT64
|
||||
cmp r3, #FFI_TYPE_SINT64
|
||||
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
|
||||
cmpne r3, #FFI_TYPE_DOUBLE
|
||||
#endif
|
||||
stmeqia r2, {r0, r1}
|
||||
|
||||
#if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
|
||||
beq LSYM(Lepilogue)
|
||||
|
||||
@ return FLOAT
|
||||
cmp r3, #FFI_TYPE_FLOAT
|
||||
stfeqs f0, [r2]
|
||||
beq LSYM(Lepilogue)
|
||||
|
||||
@ return DOUBLE or LONGDOUBLE
|
||||
cmp r3, #FFI_TYPE_DOUBLE
|
||||
stfeqd f0, [r2]
|
||||
#endif
|
||||
|
||||
LSYM(Lepilogue):
|
||||
RETLDM "r0-r3,fp"
|
||||
|
||||
.ffi_call_SYSV_end:
|
||||
UNWIND .fnend
|
||||
.size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
|
||||
|
||||
/*
|
||||
unsigned int FFI_HIDDEN
|
||||
ffi_closure_SYSV_inner (closure, respp, args)
|
||||
ffi_closure *closure;
|
||||
void **respp;
|
||||
void *args;
|
||||
*/
|
||||
|
||||
ARM_FUNC_START ffi_closure_SYSV
|
||||
UNWIND .pad #16
|
||||
add ip, sp, #16
|
||||
stmfd sp!, {ip, lr}
|
||||
UNWIND .save {r0, lr}
|
||||
add r2, sp, #8
|
||||
.pad #16
|
||||
sub sp, sp, #16
|
||||
str sp, [sp, #8]
|
||||
add r1, sp, #8
|
||||
bl ffi_closure_SYSV_inner
|
||||
cmp r0, #FFI_TYPE_INT
|
||||
beq .Lretint
|
||||
|
||||
cmp r0, #FFI_TYPE_FLOAT
|
||||
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
|
||||
beq .Lretint
|
||||
#else
|
||||
beq .Lretfloat
|
||||
#endif
|
||||
|
||||
cmp r0, #FFI_TYPE_DOUBLE
|
||||
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
|
||||
beq .Lretlonglong
|
||||
#else
|
||||
beq .Lretdouble
|
||||
#endif
|
||||
|
||||
cmp r0, #FFI_TYPE_LONGDOUBLE
|
||||
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
|
||||
beq .Lretlonglong
|
||||
#else
|
||||
beq .Lretlongdouble
|
||||
#endif
|
||||
|
||||
cmp r0, #FFI_TYPE_SINT64
|
||||
beq .Lretlonglong
|
||||
.Lclosure_epilogue:
|
||||
add sp, sp, #16
|
||||
ldmfd sp, {sp, pc}
|
||||
.Lretint:
|
||||
ldr r0, [sp]
|
||||
b .Lclosure_epilogue
|
||||
.Lretlonglong:
|
||||
ldr r0, [sp]
|
||||
ldr r1, [sp, #4]
|
||||
b .Lclosure_epilogue
|
||||
|
||||
#if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
|
||||
.Lretfloat:
|
||||
ldfs f0, [sp]
|
||||
b .Lclosure_epilogue
|
||||
.Lretdouble:
|
||||
ldfd f0, [sp]
|
||||
b .Lclosure_epilogue
|
||||
.Lretlongdouble:
|
||||
ldfd f0, [sp]
|
||||
b .Lclosure_epilogue
|
||||
#endif
|
||||
|
||||
.ffi_closure_SYSV_end:
|
||||
UNWIND .fnend
|
||||
.size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
#endif
|
||||
610
src/closures.c
Normal file
610
src/closures.c
Normal file
@@ -0,0 +1,610 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
closures.c - Copyright (c) 2007 Red Hat, Inc.
|
||||
Copyright (C) 2007 Free Software Foundation, Inc
|
||||
|
||||
Code to allocate and deallocate memory for closures.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#if defined __linux__ && !defined _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#ifndef FFI_MMAP_EXEC_WRIT
|
||||
# if __gnu_linux__
|
||||
/* This macro indicates it may be forbidden to map anonymous memory
|
||||
with both write and execute permission. Code compiled when this
|
||||
option is defined will attempt to map such pages once, but if it
|
||||
fails, it falls back to creating a temporary file in a writable and
|
||||
executable filesystem and mapping pages from it into separate
|
||||
locations in the virtual memory space, one location writable and
|
||||
another executable. */
|
||||
# define FFI_MMAP_EXEC_WRIT 1
|
||||
# define HAVE_MNTENT 1
|
||||
# endif
|
||||
# if defined(X86_WIN32) || defined(X86_WIN64)
|
||||
/* Windows systems may have Data Execution Protection (DEP) enabled,
|
||||
which requires the use of VirtualMalloc/VirtualFree to alloc/free
|
||||
executable memory. */
|
||||
# define FFI_MMAP_EXEC_WRIT 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if FFI_MMAP_EXEC_WRIT && !defined FFI_MMAP_EXEC_SELINUX
|
||||
# ifdef __linux__
|
||||
/* When defined to 1 check for SELinux and if SELinux is active,
|
||||
don't attempt PROT_EXEC|PROT_WRITE mapping at all, as that
|
||||
might cause audit messages. */
|
||||
# define FFI_MMAP_EXEC_SELINUX 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if FFI_CLOSURES
|
||||
|
||||
# if FFI_MMAP_EXEC_WRIT
|
||||
|
||||
#define USE_LOCKS 1
|
||||
#define USE_DL_PREFIX 1
|
||||
#ifdef __GNUC__
|
||||
#ifndef USE_BUILTIN_FFS
|
||||
#define USE_BUILTIN_FFS 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* We need to use mmap, not sbrk. */
|
||||
#define HAVE_MORECORE 0
|
||||
|
||||
/* We could, in theory, support mremap, but it wouldn't buy us anything. */
|
||||
#define HAVE_MREMAP 0
|
||||
|
||||
/* We have no use for this, so save some code and data. */
|
||||
#define NO_MALLINFO 1
|
||||
|
||||
/* We need all allocations to be in regular segments, otherwise we
|
||||
lose track of the corresponding code address. */
|
||||
#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
|
||||
|
||||
/* Don't allocate more than a page unless needed. */
|
||||
#define DEFAULT_GRANULARITY ((size_t)malloc_getpagesize)
|
||||
|
||||
#if FFI_CLOSURE_TEST
|
||||
/* Don't release single pages, to avoid a worst-case scenario of
|
||||
continuously allocating and releasing single pages, but release
|
||||
pairs of pages, which should do just as well given that allocations
|
||||
are likely to be small. */
|
||||
#define DEFAULT_TRIM_THRESHOLD ((size_t)malloc_getpagesize)
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#if !defined(X86_WIN32) && !defined(X86_WIN64)
|
||||
#ifdef HAVE_MNTENT
|
||||
#include <mntent.h>
|
||||
#endif /* HAVE_MNTENT */
|
||||
#include <sys/param.h>
|
||||
#include <pthread.h>
|
||||
|
||||
/* We don't want sys/mman.h to be included after we redefine mmap and
|
||||
dlmunmap. */
|
||||
#include <sys/mman.h>
|
||||
#define LACKS_SYS_MMAN_H 1
|
||||
|
||||
#if FFI_MMAP_EXEC_SELINUX
|
||||
#include <sys/statfs.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static int selinux_enabled = -1;
|
||||
|
||||
static int
|
||||
selinux_enabled_check (void)
|
||||
{
|
||||
struct statfs sfs;
|
||||
FILE *f;
|
||||
char *buf = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
if (statfs ("/selinux", &sfs) >= 0
|
||||
&& (unsigned int) sfs.f_type == 0xf97cff8cU)
|
||||
return 1;
|
||||
f = fopen ("/proc/mounts", "r");
|
||||
if (f == NULL)
|
||||
return 0;
|
||||
while (getline (&buf, &len, f) >= 0)
|
||||
{
|
||||
char *p = strchr (buf, ' ');
|
||||
if (p == NULL)
|
||||
break;
|
||||
p = strchr (p + 1, ' ');
|
||||
if (p == NULL)
|
||||
break;
|
||||
if (strncmp (p + 1, "selinuxfs ", 10) != 0)
|
||||
{
|
||||
free (buf);
|
||||
fclose (f);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
free (buf);
|
||||
fclose (f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define is_selinux_enabled() (selinux_enabled >= 0 ? selinux_enabled \
|
||||
: (selinux_enabled = selinux_enabled_check ()))
|
||||
|
||||
#else
|
||||
|
||||
#define is_selinux_enabled() 0
|
||||
|
||||
#endif /* !FFI_MMAP_EXEC_SELINUX */
|
||||
|
||||
#elif defined (__CYGWIN__)
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
/* Cygwin is Linux-like, but not quite that Linux-like. */
|
||||
#define is_selinux_enabled() 0
|
||||
|
||||
#endif /* !defined(X86_WIN32) && !defined(X86_WIN64) */
|
||||
|
||||
/* Declare all functions defined in dlmalloc.c as static. */
|
||||
static void *dlmalloc(size_t);
|
||||
static void dlfree(void*);
|
||||
static void *dlcalloc(size_t, size_t) MAYBE_UNUSED;
|
||||
static void *dlrealloc(void *, size_t) MAYBE_UNUSED;
|
||||
static void *dlmemalign(size_t, size_t) MAYBE_UNUSED;
|
||||
static void *dlvalloc(size_t) MAYBE_UNUSED;
|
||||
static int dlmallopt(int, int) MAYBE_UNUSED;
|
||||
static size_t dlmalloc_footprint(void) MAYBE_UNUSED;
|
||||
static size_t dlmalloc_max_footprint(void) MAYBE_UNUSED;
|
||||
static void** dlindependent_calloc(size_t, size_t, void**) MAYBE_UNUSED;
|
||||
static void** dlindependent_comalloc(size_t, size_t*, void**) MAYBE_UNUSED;
|
||||
static void *dlpvalloc(size_t) MAYBE_UNUSED;
|
||||
static int dlmalloc_trim(size_t) MAYBE_UNUSED;
|
||||
static size_t dlmalloc_usable_size(void*) MAYBE_UNUSED;
|
||||
static void dlmalloc_stats(void) MAYBE_UNUSED;
|
||||
|
||||
#if !(defined(X86_WIN32) || defined(X86_WIN64)) || defined (__CYGWIN__)
|
||||
/* Use these for mmap and munmap within dlmalloc.c. */
|
||||
static void *dlmmap(void *, size_t, int, int, int, off_t);
|
||||
static int dlmunmap(void *, size_t);
|
||||
#endif /* !(defined(X86_WIN32) || defined(X86_WIN64)) || defined (__CYGWIN__) */
|
||||
|
||||
#define mmap dlmmap
|
||||
#define munmap dlmunmap
|
||||
|
||||
#include "dlmalloc.c"
|
||||
|
||||
#undef mmap
|
||||
#undef munmap
|
||||
|
||||
#if !(defined(X86_WIN32) || defined(X86_WIN64)) || defined (__CYGWIN__)
|
||||
|
||||
/* A mutex used to synchronize access to *exec* variables in this file. */
|
||||
static pthread_mutex_t open_temp_exec_file_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/* A file descriptor of a temporary file from which we'll map
|
||||
executable pages. */
|
||||
static int execfd = -1;
|
||||
|
||||
/* The amount of space already allocated from the temporary file. */
|
||||
static size_t execsize = 0;
|
||||
|
||||
/* Open a temporary file name, and immediately unlink it. */
|
||||
static int
|
||||
open_temp_exec_file_name (char *name)
|
||||
{
|
||||
int fd = mkstemp (name);
|
||||
|
||||
if (fd != -1)
|
||||
unlink (name);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* Open a temporary file in the named directory. */
|
||||
static int
|
||||
open_temp_exec_file_dir (const char *dir)
|
||||
{
|
||||
static const char suffix[] = "/ffiXXXXXX";
|
||||
int lendir = strlen (dir);
|
||||
char *tempname = __builtin_alloca (lendir + sizeof (suffix));
|
||||
|
||||
if (!tempname)
|
||||
return -1;
|
||||
|
||||
memcpy (tempname, dir, lendir);
|
||||
memcpy (tempname + lendir, suffix, sizeof (suffix));
|
||||
|
||||
return open_temp_exec_file_name (tempname);
|
||||
}
|
||||
|
||||
/* Open a temporary file in the directory in the named environment
|
||||
variable. */
|
||||
static int
|
||||
open_temp_exec_file_env (const char *envvar)
|
||||
{
|
||||
const char *value = getenv (envvar);
|
||||
|
||||
if (!value)
|
||||
return -1;
|
||||
|
||||
return open_temp_exec_file_dir (value);
|
||||
}
|
||||
|
||||
#ifdef HAVE_MNTENT
|
||||
/* Open a temporary file in an executable and writable mount point
|
||||
listed in the mounts file. Subsequent calls with the same mounts
|
||||
keep searching for mount points in the same file. Providing NULL
|
||||
as the mounts file closes the file. */
|
||||
static int
|
||||
open_temp_exec_file_mnt (const char *mounts)
|
||||
{
|
||||
static const char *last_mounts;
|
||||
static FILE *last_mntent;
|
||||
|
||||
if (mounts != last_mounts)
|
||||
{
|
||||
if (last_mntent)
|
||||
endmntent (last_mntent);
|
||||
|
||||
last_mounts = mounts;
|
||||
|
||||
if (mounts)
|
||||
last_mntent = setmntent (mounts, "r");
|
||||
else
|
||||
last_mntent = NULL;
|
||||
}
|
||||
|
||||
if (!last_mntent)
|
||||
return -1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int fd;
|
||||
struct mntent mnt;
|
||||
char buf[MAXPATHLEN * 3];
|
||||
|
||||
if (getmntent_r (last_mntent, &mnt, buf, sizeof (buf)))
|
||||
return -1;
|
||||
|
||||
if (hasmntopt (&mnt, "ro")
|
||||
|| hasmntopt (&mnt, "noexec")
|
||||
|| access (mnt.mnt_dir, W_OK))
|
||||
continue;
|
||||
|
||||
fd = open_temp_exec_file_dir (mnt.mnt_dir);
|
||||
|
||||
if (fd != -1)
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_MNTENT */
|
||||
|
||||
/* Instructions to look for a location to hold a temporary file that
|
||||
can be mapped in for execution. */
|
||||
static struct
|
||||
{
|
||||
int (*func)(const char *);
|
||||
const char *arg;
|
||||
int repeat;
|
||||
} open_temp_exec_file_opts[] = {
|
||||
{ open_temp_exec_file_env, "TMPDIR", 0 },
|
||||
{ open_temp_exec_file_dir, "/tmp", 0 },
|
||||
{ open_temp_exec_file_dir, "/var/tmp", 0 },
|
||||
{ open_temp_exec_file_dir, "/dev/shm", 0 },
|
||||
{ open_temp_exec_file_env, "HOME", 0 },
|
||||
#ifdef HAVE_MNTENT
|
||||
{ open_temp_exec_file_mnt, "/etc/mtab", 1 },
|
||||
{ open_temp_exec_file_mnt, "/proc/mounts", 1 },
|
||||
#endif /* HAVE_MNTENT */
|
||||
};
|
||||
|
||||
/* Current index into open_temp_exec_file_opts. */
|
||||
static int open_temp_exec_file_opts_idx = 0;
|
||||
|
||||
/* Reset a current multi-call func, then advances to the next entry.
|
||||
If we're at the last, go back to the first and return nonzero,
|
||||
otherwise return zero. */
|
||||
static int
|
||||
open_temp_exec_file_opts_next (void)
|
||||
{
|
||||
if (open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat)
|
||||
open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func (NULL);
|
||||
|
||||
open_temp_exec_file_opts_idx++;
|
||||
if (open_temp_exec_file_opts_idx
|
||||
== (sizeof (open_temp_exec_file_opts)
|
||||
/ sizeof (*open_temp_exec_file_opts)))
|
||||
{
|
||||
open_temp_exec_file_opts_idx = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return a file descriptor of a temporary zero-sized file in a
|
||||
writable and exexutable filesystem. */
|
||||
static int
|
||||
open_temp_exec_file (void)
|
||||
{
|
||||
int fd;
|
||||
|
||||
do
|
||||
{
|
||||
fd = open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func
|
||||
(open_temp_exec_file_opts[open_temp_exec_file_opts_idx].arg);
|
||||
|
||||
if (!open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat
|
||||
|| fd == -1)
|
||||
{
|
||||
if (open_temp_exec_file_opts_next ())
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (fd == -1);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* Map in a chunk of memory from the temporary exec file into separate
|
||||
locations in the virtual memory address space, one writable and one
|
||||
executable. Returns the address of the writable portion, after
|
||||
storing an offset to the corresponding executable portion at the
|
||||
last word of the requested chunk. */
|
||||
static void *
|
||||
dlmmap_locked (void *start, size_t length, int prot, int flags, off_t offset)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
if (execfd == -1)
|
||||
{
|
||||
open_temp_exec_file_opts_idx = 0;
|
||||
retry_open:
|
||||
execfd = open_temp_exec_file ();
|
||||
if (execfd == -1)
|
||||
return MFAIL;
|
||||
}
|
||||
|
||||
offset = execsize;
|
||||
|
||||
if (ftruncate (execfd, offset + length))
|
||||
return MFAIL;
|
||||
|
||||
flags &= ~(MAP_PRIVATE | MAP_ANONYMOUS);
|
||||
flags |= MAP_SHARED;
|
||||
|
||||
ptr = mmap (NULL, length, (prot & ~PROT_WRITE) | PROT_EXEC,
|
||||
flags, execfd, offset);
|
||||
if (ptr == MFAIL)
|
||||
{
|
||||
if (!offset)
|
||||
{
|
||||
close (execfd);
|
||||
goto retry_open;
|
||||
}
|
||||
ftruncate (execfd, offset);
|
||||
return MFAIL;
|
||||
}
|
||||
else if (!offset
|
||||
&& open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat)
|
||||
open_temp_exec_file_opts_next ();
|
||||
|
||||
start = mmap (start, length, prot, flags, execfd, offset);
|
||||
|
||||
if (start == MFAIL)
|
||||
{
|
||||
munmap (ptr, length);
|
||||
ftruncate (execfd, offset);
|
||||
return start;
|
||||
}
|
||||
|
||||
mmap_exec_offset ((char *)start, length) = (char*)ptr - (char*)start;
|
||||
|
||||
execsize += length;
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
/* Map in a writable and executable chunk of memory if possible.
|
||||
Failing that, fall back to dlmmap_locked. */
|
||||
static void *
|
||||
dlmmap (void *start, size_t length, int prot,
|
||||
int flags, int fd, off_t offset)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
assert (start == NULL && length % malloc_getpagesize == 0
|
||||
&& prot == (PROT_READ | PROT_WRITE)
|
||||
&& flags == (MAP_PRIVATE | MAP_ANONYMOUS)
|
||||
&& fd == -1 && offset == 0);
|
||||
|
||||
#if FFI_CLOSURE_TEST
|
||||
printf ("mapping in %zi\n", length);
|
||||
#endif
|
||||
|
||||
if (execfd == -1 && !is_selinux_enabled ())
|
||||
{
|
||||
ptr = mmap (start, length, prot | PROT_EXEC, flags, fd, offset);
|
||||
|
||||
if (ptr != MFAIL || (errno != EPERM && errno != EACCES))
|
||||
/* Cool, no need to mess with separate segments. */
|
||||
return ptr;
|
||||
|
||||
/* If MREMAP_DUP is ever introduced and implemented, try mmap
|
||||
with ((prot & ~PROT_WRITE) | PROT_EXEC) and mremap with
|
||||
MREMAP_DUP and prot at this point. */
|
||||
}
|
||||
|
||||
if (execsize == 0 || execfd == -1)
|
||||
{
|
||||
pthread_mutex_lock (&open_temp_exec_file_mutex);
|
||||
ptr = dlmmap_locked (start, length, prot, flags, offset);
|
||||
pthread_mutex_unlock (&open_temp_exec_file_mutex);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
return dlmmap_locked (start, length, prot, flags, offset);
|
||||
}
|
||||
|
||||
/* Release memory at the given address, as well as the corresponding
|
||||
executable page if it's separate. */
|
||||
static int
|
||||
dlmunmap (void *start, size_t length)
|
||||
{
|
||||
/* We don't bother decreasing execsize or truncating the file, since
|
||||
we can't quite tell whether we're unmapping the end of the file.
|
||||
We don't expect frequent deallocation anyway. If we did, we
|
||||
could locate pages in the file by writing to the pages being
|
||||
deallocated and checking that the file contents change.
|
||||
Yuck. */
|
||||
msegmentptr seg = segment_holding (gm, start);
|
||||
void *code;
|
||||
|
||||
#if FFI_CLOSURE_TEST
|
||||
printf ("unmapping %zi\n", length);
|
||||
#endif
|
||||
|
||||
if (seg && (code = add_segment_exec_offset (start, seg)) != start)
|
||||
{
|
||||
int ret = munmap (code, length);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return munmap (start, length);
|
||||
}
|
||||
|
||||
#if FFI_CLOSURE_FREE_CODE
|
||||
/* Return segment holding given code address. */
|
||||
static msegmentptr
|
||||
segment_holding_code (mstate m, char* addr)
|
||||
{
|
||||
msegmentptr sp = &m->seg;
|
||||
for (;;) {
|
||||
if (addr >= add_segment_exec_offset (sp->base, sp)
|
||||
&& addr < add_segment_exec_offset (sp->base, sp) + sp->size)
|
||||
return sp;
|
||||
if ((sp = sp->next) == 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !(defined(X86_WIN32) || defined(X86_WIN64)) || defined (__CYGWIN__) */
|
||||
|
||||
/* Allocate a chunk of memory with the given size. Returns a pointer
|
||||
to the writable address, and sets *CODE to the executable
|
||||
corresponding virtual address. */
|
||||
void *
|
||||
ffi_closure_alloc (size_t size, void **code)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
if (!code)
|
||||
return NULL;
|
||||
|
||||
ptr = dlmalloc (size);
|
||||
|
||||
if (ptr)
|
||||
{
|
||||
msegmentptr seg = segment_holding (gm, ptr);
|
||||
|
||||
*code = add_segment_exec_offset (ptr, seg);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* Release a chunk of memory allocated with ffi_closure_alloc. If
|
||||
FFI_CLOSURE_FREE_CODE is nonzero, the given address can be the
|
||||
writable or the executable address given. Otherwise, only the
|
||||
writable address can be provided here. */
|
||||
void
|
||||
ffi_closure_free (void *ptr)
|
||||
{
|
||||
#if FFI_CLOSURE_FREE_CODE
|
||||
msegmentptr seg = segment_holding_code (gm, ptr);
|
||||
|
||||
if (seg)
|
||||
ptr = sub_segment_exec_offset (ptr, seg);
|
||||
#endif
|
||||
|
||||
dlfree (ptr);
|
||||
}
|
||||
|
||||
|
||||
#if FFI_CLOSURE_TEST
|
||||
/* Do some internal sanity testing to make sure allocation and
|
||||
deallocation of pages are working as intended. */
|
||||
int main ()
|
||||
{
|
||||
void *p[3];
|
||||
#define GET(idx, len) do { p[idx] = dlmalloc (len); printf ("allocated %zi for p[%i]\n", (len), (idx)); } while (0)
|
||||
#define PUT(idx) do { printf ("freeing p[%i]\n", (idx)); dlfree (p[idx]); } while (0)
|
||||
GET (0, malloc_getpagesize / 2);
|
||||
GET (1, 2 * malloc_getpagesize - 64 * sizeof (void*));
|
||||
PUT (1);
|
||||
GET (1, 2 * malloc_getpagesize);
|
||||
GET (2, malloc_getpagesize / 2);
|
||||
PUT (1);
|
||||
PUT (0);
|
||||
PUT (2);
|
||||
return 0;
|
||||
}
|
||||
#endif /* FFI_CLOSURE_TEST */
|
||||
# else /* ! FFI_MMAP_EXEC_WRIT */
|
||||
|
||||
/* On many systems, memory returned by malloc is writable and
|
||||
executable, so just use it. */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
void *
|
||||
ffi_closure_alloc (size_t size, void **code)
|
||||
{
|
||||
if (!code)
|
||||
return NULL;
|
||||
|
||||
return *code = malloc (size);
|
||||
}
|
||||
|
||||
void
|
||||
ffi_closure_free (void *ptr)
|
||||
{
|
||||
free (ptr);
|
||||
}
|
||||
|
||||
# endif /* ! FFI_MMAP_EXEC_WRIT */
|
||||
#endif /* FFI_CLOSURES */
|
||||
130
src/cris/.svn/entries
Normal file
130
src/cris/.svn/entries
Normal file
@@ -0,0 +1,130 @@
|
||||
10
|
||||
|
||||
dir
|
||||
152280
|
||||
svn://gcc.gnu.org/svn/gcc/trunk/libffi/src/cris
|
||||
svn://gcc.gnu.org/svn/gcc
|
||||
|
||||
|
||||
|
||||
2009-06-04T15:11:12.475454Z
|
||||
148171
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
138bc75d-0d04-0410-961f-82ee72b054a4
|
||||
|
||||
ffitarget.h
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:02.000000Z
|
||||
b0de7e4f36e492338d0076bd66610cd0
|
||||
2009-06-04T15:11:12.475454Z
|
||||
148171
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1963
|
||||
|
||||
ffi.c
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-04-24T17:46:15.000000Z
|
||||
5d7af3480697d2ceab7f4ec35baa9d26
|
||||
2007-03-07T07:27:25.150115Z
|
||||
122652
|
||||
aoliva
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
9658
|
||||
|
||||
sysv.S
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-04-24T17:46:15.000000Z
|
||||
b17e59bf6ba716c77cd9ca7a4e39e672
|
||||
2005-04-18T17:08:58.000000Z
|
||||
98332
|
||||
hp
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
5479
|
||||
|
||||
383
src/cris/.svn/text-base/ffi.c.svn-base
Normal file
383
src/cris/.svn/text-base/ffi.c.svn-base
Normal file
@@ -0,0 +1,383 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1998 Cygnus Solutions
|
||||
Copyright (c) 2004 Simon Posnjak
|
||||
Copyright (c) 2005 Axis Communications AB
|
||||
Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
|
||||
CRIS 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 SIMON POSNJAK 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
|
||||
|
||||
static ffi_status
|
||||
initialize_aggregate_packed_struct (ffi_type * arg)
|
||||
{
|
||||
ffi_type **ptr;
|
||||
|
||||
FFI_ASSERT (arg != NULL);
|
||||
|
||||
FFI_ASSERT (arg->elements != NULL);
|
||||
FFI_ASSERT (arg->size == 0);
|
||||
FFI_ASSERT (arg->alignment == 0);
|
||||
|
||||
ptr = &(arg->elements[0]);
|
||||
|
||||
while ((*ptr) != NULL)
|
||||
{
|
||||
if (((*ptr)->size == 0)
|
||||
&& (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
FFI_ASSERT (ffi_type_test ((*ptr)));
|
||||
|
||||
arg->size += (*ptr)->size;
|
||||
|
||||
arg->alignment = (arg->alignment > (*ptr)->alignment) ?
|
||||
arg->alignment : (*ptr)->alignment;
|
||||
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if (arg->size == 0)
|
||||
return FFI_BAD_TYPEDEF;
|
||||
else
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
int
|
||||
ffi_prep_args (char *stack, extended_cif * ecif)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int struct_count = 0;
|
||||
void **p_argv;
|
||||
char *argp;
|
||||
ffi_type **p_arg;
|
||||
|
||||
argp = stack;
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
(i != 0); i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_STRUCT:
|
||||
{
|
||||
z = (*p_arg)->size;
|
||||
if (z <= 4)
|
||||
{
|
||||
memcpy (argp, *p_argv, z);
|
||||
z = 4;
|
||||
}
|
||||
else if (z <= 8)
|
||||
{
|
||||
memcpy (argp, *p_argv, z);
|
||||
z = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int uiLocOnStack;
|
||||
z = sizeof (void *);
|
||||
uiLocOnStack = 4 * ecif->cif->nargs + struct_count;
|
||||
struct_count = struct_count + (*p_arg)->size;
|
||||
*(unsigned int *) argp =
|
||||
(unsigned int) (UINT32 *) (stack + uiLocOnStack);
|
||||
memcpy ((stack + uiLocOnStack), *p_argv, (*p_arg)->size);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof (int))
|
||||
{
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int) *(SINT8 *) (*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp =
|
||||
(unsigned int) *(UINT8 *) (*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int) *(SINT16 *) (*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp =
|
||||
(unsigned int) *(UINT16 *) (*p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
}
|
||||
z = sizeof (int);
|
||||
}
|
||||
else if (z == sizeof (int))
|
||||
*(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv);
|
||||
else
|
||||
memcpy (argp, *p_argv, z);
|
||||
break;
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
|
||||
return (struct_count);
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_cif (ffi_cif * cif,
|
||||
ffi_abi abi, unsigned int nargs,
|
||||
ffi_type * rtype, ffi_type ** atypes)
|
||||
{
|
||||
unsigned bytes = 0;
|
||||
unsigned int i;
|
||||
ffi_type **ptr;
|
||||
|
||||
FFI_ASSERT (cif != NULL);
|
||||
FFI_ASSERT ((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
|
||||
|
||||
cif->abi = abi;
|
||||
cif->arg_types = atypes;
|
||||
cif->nargs = nargs;
|
||||
cif->rtype = rtype;
|
||||
|
||||
cif->flags = 0;
|
||||
|
||||
if ((cif->rtype->size == 0)
|
||||
&& (initialize_aggregate_packed_struct (cif->rtype) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
FFI_ASSERT_VALID_TYPE (cif->rtype);
|
||||
|
||||
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
||||
{
|
||||
if (((*ptr)->size == 0)
|
||||
&& (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
FFI_ASSERT_VALID_TYPE (*ptr);
|
||||
|
||||
if (((*ptr)->alignment - 1) & bytes)
|
||||
bytes = ALIGN (bytes, (*ptr)->alignment);
|
||||
if ((*ptr)->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
if ((*ptr)->size > 8)
|
||||
{
|
||||
bytes += (*ptr)->size;
|
||||
bytes += sizeof (void *);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((*ptr)->size > 4)
|
||||
bytes += 8;
|
||||
else
|
||||
bytes += 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
bytes += STACK_ARG_SIZE ((*ptr)->size);
|
||||
}
|
||||
|
||||
cif->bytes = bytes;
|
||||
|
||||
return ffi_prep_cif_machdep (cif);
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep (ffi_cif * cif)
|
||||
{
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_STRUCT:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern void ffi_call_SYSV (int (*)(char *, extended_cif *),
|
||||
extended_cif *,
|
||||
unsigned, unsigned, unsigned *, void (*fn) ())
|
||||
__attribute__ ((__visibility__ ("hidden")));
|
||||
|
||||
void
|
||||
ffi_call (ffi_cif * cif, void (*fn) (), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Because the following variables are not exported outside libffi, we
|
||||
mark them hidden. */
|
||||
|
||||
/* Assembly code for the jump stub. */
|
||||
extern const char ffi_cris_trampoline_template[]
|
||||
__attribute__ ((__visibility__ ("hidden")));
|
||||
|
||||
/* Offset into ffi_cris_trampoline_template of where to put the
|
||||
ffi_prep_closure_inner function. */
|
||||
extern const int ffi_cris_trampoline_fn_offset
|
||||
__attribute__ ((__visibility__ ("hidden")));
|
||||
|
||||
/* Offset into ffi_cris_trampoline_template of where to put the
|
||||
closure data. */
|
||||
extern const int ffi_cris_trampoline_closure_offset
|
||||
__attribute__ ((__visibility__ ("hidden")));
|
||||
|
||||
/* This function is sibling-called (jumped to) by the closure
|
||||
trampoline. We get R10..R13 at PARAMS[0..3] and a copy of [SP] at
|
||||
PARAMS[4] to simplify handling of a straddling parameter. A copy
|
||||
of R9 is at PARAMS[5] and SP at PARAMS[6]. These parameters are
|
||||
put at the appropriate place in CLOSURE which is then executed and
|
||||
the return value is passed back to the caller. */
|
||||
|
||||
static unsigned long long
|
||||
ffi_prep_closure_inner (void **params, ffi_closure* closure)
|
||||
{
|
||||
char *register_args = (char *) params;
|
||||
void *struct_ret = params[5];
|
||||
char *stack_args = params[6];
|
||||
char *ptr = register_args;
|
||||
ffi_cif *cif = closure->cif;
|
||||
ffi_type **arg_types = cif->arg_types;
|
||||
|
||||
/* Max room needed is number of arguments as 64-bit values. */
|
||||
void **avalue = alloca (closure->cif->nargs * sizeof(void *));
|
||||
int i;
|
||||
int doing_regs;
|
||||
long long llret = 0;
|
||||
|
||||
/* Find the address of each argument. */
|
||||
for (i = 0, doing_regs = 1; i < cif->nargs; i++)
|
||||
{
|
||||
/* Types up to and including 8 bytes go by-value. */
|
||||
if (arg_types[i]->size <= 4)
|
||||
{
|
||||
avalue[i] = ptr;
|
||||
ptr += 4;
|
||||
}
|
||||
else if (arg_types[i]->size <= 8)
|
||||
{
|
||||
avalue[i] = ptr;
|
||||
ptr += 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
FFI_ASSERT (arg_types[i]->type == FFI_TYPE_STRUCT);
|
||||
|
||||
/* Passed by-reference, so copy the pointer. */
|
||||
avalue[i] = *(void **) ptr;
|
||||
ptr += 4;
|
||||
}
|
||||
|
||||
/* If we've handled more arguments than fit in registers, start
|
||||
looking at the those passed on the stack. Step over the
|
||||
first one if we had a straddling parameter. */
|
||||
if (doing_regs && ptr >= register_args + 4*4)
|
||||
{
|
||||
ptr = stack_args + ((ptr > register_args + 4*4) ? 4 : 0);
|
||||
doing_regs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
(closure->fun) (cif,
|
||||
|
||||
cif->rtype->type == FFI_TYPE_STRUCT
|
||||
/* The caller allocated space for the return
|
||||
structure, and passed a pointer to this space in
|
||||
R9. */
|
||||
? struct_ret
|
||||
|
||||
/* We take advantage of being able to ignore that
|
||||
the high part isn't set if the return value is
|
||||
not in R10:R11, but in R10 only. */
|
||||
: (void *) &llret,
|
||||
|
||||
avalue, closure->user_data);
|
||||
|
||||
return llret;
|
||||
}
|
||||
|
||||
/* API function: Prepare the trampoline. */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif *, void *, void **, void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
void *innerfn = ffi_prep_closure_inner;
|
||||
FFI_ASSERT (cif->abi == FFI_SYSV);
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
memcpy (closure->tramp, ffi_cris_trampoline_template,
|
||||
FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE);
|
||||
memcpy (closure->tramp + ffi_cris_trampoline_fn_offset,
|
||||
&innerfn, sizeof (void *));
|
||||
memcpy (closure->tramp + ffi_cris_trampoline_closure_offset,
|
||||
&codeloc, sizeof (void *));
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
51
src/cris/.svn/text-base/ffitarget.h.svn-base
Normal file
51
src/cris/.svn/text-base/ffitarget.h.svn-base
Normal file
@@ -0,0 +1,51 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for CRIS.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_SYSV,
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE 36
|
||||
#define FFI_CRIS_TRAMPOLINE_DATA_PART_SIZE (7*4)
|
||||
#define FFI_TRAMPOLINE_SIZE \
|
||||
(FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE + FFI_CRIS_TRAMPOLINE_DATA_PART_SIZE)
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
215
src/cris/.svn/text-base/sysv.S.svn-base
Normal file
215
src/cris/.svn/text-base/sysv.S.svn-base
Normal file
@@ -0,0 +1,215 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 2004 Simon Posnjak
|
||||
Copyright (c) 2005 Axis Communications AB
|
||||
|
||||
CRIS 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 SIMON POSNJAK 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>
|
||||
#define CONCAT(x,y) x ## y
|
||||
#define XCONCAT(x,y) CONCAT (x, y)
|
||||
#define L(x) XCONCAT (__USER_LABEL_PREFIX__, x)
|
||||
|
||||
.text
|
||||
|
||||
;; OK, when we get called we should have this (according to
|
||||
;; AXIS ETRAX 100LX Programmer's Manual chapter 6.3).
|
||||
;;
|
||||
;; R10: ffi_prep_args (func. pointer)
|
||||
;; R11: &ecif
|
||||
;; R12: cif->bytes
|
||||
;; R13: fig->flags
|
||||
;; sp+0: ecif.rvalue
|
||||
;; sp+4: fn (function pointer to the function that we need to call)
|
||||
|
||||
.globl L(ffi_call_SYSV)
|
||||
.type L(ffi_call_SYSV),@function
|
||||
.hidden L(ffi_call_SYSV)
|
||||
|
||||
L(ffi_call_SYSV):
|
||||
;; Save the regs to the stack.
|
||||
push $srp
|
||||
;; Used for stack pointer saving.
|
||||
push $r6
|
||||
;; Used for function address pointer.
|
||||
push $r7
|
||||
;; Used for stack pointer saving.
|
||||
push $r8
|
||||
;; We save fig->flags to stack we will need them after we
|
||||
;; call The Function.
|
||||
push $r13
|
||||
|
||||
;; Saving current stack pointer.
|
||||
move.d $sp,$r8
|
||||
move.d $sp,$r6
|
||||
|
||||
;; Move address of ffi_prep_args to r13.
|
||||
move.d $r10,$r13
|
||||
|
||||
;; Make room on the stack for the args of fn.
|
||||
sub.d $r12,$sp
|
||||
|
||||
;; Function void ffi_prep_args(char *stack, extended_cif *ecif) parameters are:
|
||||
;; r10 <-- stack pointer
|
||||
;; r11 <-- &ecif (already there)
|
||||
move.d $sp,$r10
|
||||
|
||||
;; Call the function.
|
||||
jsr $r13
|
||||
|
||||
;; Save the size of the structures which are passed on stack.
|
||||
move.d $r10,$r7
|
||||
|
||||
;; Move first four args in to r10..r13.
|
||||
move.d [$sp+0],$r10
|
||||
move.d [$sp+4],$r11
|
||||
move.d [$sp+8],$r12
|
||||
move.d [$sp+12],$r13
|
||||
|
||||
;; Adjust the stack and check if any parameters are given on stack.
|
||||
addq 16,$sp
|
||||
sub.d $r7,$r6
|
||||
cmp.d $sp,$r6
|
||||
|
||||
bpl go_on
|
||||
nop
|
||||
|
||||
go_on_no_params_on_stack:
|
||||
move.d $r6,$sp
|
||||
|
||||
go_on:
|
||||
;; Discover if we need to put rval address in to r9.
|
||||
move.d [$r8+0],$r7
|
||||
cmpq FFI_TYPE_STRUCT,$r7
|
||||
bne call_now
|
||||
nop
|
||||
|
||||
;; Move rval address to $r9.
|
||||
move.d [$r8+20],$r9
|
||||
|
||||
call_now:
|
||||
;; Move address of The Function in to r7.
|
||||
move.d [$r8+24],$r7
|
||||
|
||||
;; Call The Function.
|
||||
jsr $r7
|
||||
|
||||
;; Reset stack.
|
||||
move.d $r8,$sp
|
||||
|
||||
;; Load rval type (fig->flags) in to r13.
|
||||
pop $r13
|
||||
|
||||
;; Detect rval type.
|
||||
cmpq FFI_TYPE_VOID,$r13
|
||||
beq epilogue
|
||||
|
||||
cmpq FFI_TYPE_STRUCT,$r13
|
||||
beq epilogue
|
||||
|
||||
cmpq FFI_TYPE_DOUBLE,$r13
|
||||
beq return_double_or_longlong
|
||||
|
||||
cmpq FFI_TYPE_UINT64,$r13
|
||||
beq return_double_or_longlong
|
||||
|
||||
cmpq FFI_TYPE_SINT64,$r13
|
||||
beq return_double_or_longlong
|
||||
nop
|
||||
|
||||
;; Just return the 32 bit value.
|
||||
ba return
|
||||
nop
|
||||
|
||||
return_double_or_longlong:
|
||||
;; Load half of the rval to r10 and the other half to r11.
|
||||
move.d [$sp+16],$r13
|
||||
move.d $r10,[$r13]
|
||||
addq 4,$r13
|
||||
move.d $r11,[$r13]
|
||||
ba epilogue
|
||||
nop
|
||||
|
||||
return:
|
||||
;; Load the rval to r10.
|
||||
move.d [$sp+16],$r13
|
||||
move.d $r10,[$r13]
|
||||
|
||||
epilogue:
|
||||
pop $r8
|
||||
pop $r7
|
||||
pop $r6
|
||||
Jump [$sp+]
|
||||
|
||||
.size ffi_call_SYSV,.-ffi_call_SYSV
|
||||
|
||||
/* Save R10..R13 into an array, somewhat like varargs. Copy the next
|
||||
argument too, to simplify handling of any straddling parameter.
|
||||
Save R9 and SP after those. Jump to function handling the rest.
|
||||
Since this is a template, copied and the main function filled in by
|
||||
the user. */
|
||||
|
||||
.globl L(ffi_cris_trampoline_template)
|
||||
.type L(ffi_cris_trampoline_template),@function
|
||||
.hidden L(ffi_cris_trampoline_template)
|
||||
|
||||
L(ffi_cris_trampoline_template):
|
||||
0:
|
||||
/* The value we get for "PC" is right after the prefix instruction,
|
||||
two bytes from the beginning, i.e. 0b+2. */
|
||||
move.d $r10,[$pc+2f-(0b+2)]
|
||||
move.d $pc,$r10
|
||||
1:
|
||||
addq 2f-1b+4,$r10
|
||||
move.d $r11,[$r10+]
|
||||
move.d $r12,[$r10+]
|
||||
move.d $r13,[$r10+]
|
||||
move.d [$sp],$r11
|
||||
move.d $r11,[$r10+]
|
||||
move.d $r9,[$r10+]
|
||||
move.d $sp,[$r10+]
|
||||
subq FFI_CRIS_TRAMPOLINE_DATA_PART_SIZE,$r10
|
||||
move.d 0,$r11
|
||||
3:
|
||||
jump 0
|
||||
2:
|
||||
.size ffi_cris_trampoline_template,.-0b
|
||||
|
||||
/* This macro create a constant usable as "extern const int \name" in
|
||||
C from within libffi, when \name has no prefix decoration. */
|
||||
|
||||
.macro const name,value
|
||||
.globl \name
|
||||
.type \name,@object
|
||||
.hidden \name
|
||||
\name:
|
||||
.dword \value
|
||||
.size \name,4
|
||||
.endm
|
||||
|
||||
/* Constants for offsets within the trampoline. We could do this with
|
||||
just symbols, avoiding memory contents and memory accesses, but the
|
||||
C usage code would look a bit stranger. */
|
||||
|
||||
const L(ffi_cris_trampoline_fn_offset),2b-4-0b
|
||||
const L(ffi_cris_trampoline_closure_offset),3b-4-0b
|
||||
383
src/cris/ffi.c
Normal file
383
src/cris/ffi.c
Normal file
@@ -0,0 +1,383 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1998 Cygnus Solutions
|
||||
Copyright (c) 2004 Simon Posnjak
|
||||
Copyright (c) 2005 Axis Communications AB
|
||||
Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
|
||||
CRIS 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 SIMON POSNJAK 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
|
||||
|
||||
static ffi_status
|
||||
initialize_aggregate_packed_struct (ffi_type * arg)
|
||||
{
|
||||
ffi_type **ptr;
|
||||
|
||||
FFI_ASSERT (arg != NULL);
|
||||
|
||||
FFI_ASSERT (arg->elements != NULL);
|
||||
FFI_ASSERT (arg->size == 0);
|
||||
FFI_ASSERT (arg->alignment == 0);
|
||||
|
||||
ptr = &(arg->elements[0]);
|
||||
|
||||
while ((*ptr) != NULL)
|
||||
{
|
||||
if (((*ptr)->size == 0)
|
||||
&& (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
FFI_ASSERT (ffi_type_test ((*ptr)));
|
||||
|
||||
arg->size += (*ptr)->size;
|
||||
|
||||
arg->alignment = (arg->alignment > (*ptr)->alignment) ?
|
||||
arg->alignment : (*ptr)->alignment;
|
||||
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if (arg->size == 0)
|
||||
return FFI_BAD_TYPEDEF;
|
||||
else
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
int
|
||||
ffi_prep_args (char *stack, extended_cif * ecif)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int struct_count = 0;
|
||||
void **p_argv;
|
||||
char *argp;
|
||||
ffi_type **p_arg;
|
||||
|
||||
argp = stack;
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
(i != 0); i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_STRUCT:
|
||||
{
|
||||
z = (*p_arg)->size;
|
||||
if (z <= 4)
|
||||
{
|
||||
memcpy (argp, *p_argv, z);
|
||||
z = 4;
|
||||
}
|
||||
else if (z <= 8)
|
||||
{
|
||||
memcpy (argp, *p_argv, z);
|
||||
z = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int uiLocOnStack;
|
||||
z = sizeof (void *);
|
||||
uiLocOnStack = 4 * ecif->cif->nargs + struct_count;
|
||||
struct_count = struct_count + (*p_arg)->size;
|
||||
*(unsigned int *) argp =
|
||||
(unsigned int) (UINT32 *) (stack + uiLocOnStack);
|
||||
memcpy ((stack + uiLocOnStack), *p_argv, (*p_arg)->size);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof (int))
|
||||
{
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int) *(SINT8 *) (*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp =
|
||||
(unsigned int) *(UINT8 *) (*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int) *(SINT16 *) (*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp =
|
||||
(unsigned int) *(UINT16 *) (*p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
}
|
||||
z = sizeof (int);
|
||||
}
|
||||
else if (z == sizeof (int))
|
||||
*(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv);
|
||||
else
|
||||
memcpy (argp, *p_argv, z);
|
||||
break;
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
|
||||
return (struct_count);
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_cif (ffi_cif * cif,
|
||||
ffi_abi abi, unsigned int nargs,
|
||||
ffi_type * rtype, ffi_type ** atypes)
|
||||
{
|
||||
unsigned bytes = 0;
|
||||
unsigned int i;
|
||||
ffi_type **ptr;
|
||||
|
||||
FFI_ASSERT (cif != NULL);
|
||||
FFI_ASSERT ((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
|
||||
|
||||
cif->abi = abi;
|
||||
cif->arg_types = atypes;
|
||||
cif->nargs = nargs;
|
||||
cif->rtype = rtype;
|
||||
|
||||
cif->flags = 0;
|
||||
|
||||
if ((cif->rtype->size == 0)
|
||||
&& (initialize_aggregate_packed_struct (cif->rtype) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
FFI_ASSERT_VALID_TYPE (cif->rtype);
|
||||
|
||||
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
||||
{
|
||||
if (((*ptr)->size == 0)
|
||||
&& (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
FFI_ASSERT_VALID_TYPE (*ptr);
|
||||
|
||||
if (((*ptr)->alignment - 1) & bytes)
|
||||
bytes = ALIGN (bytes, (*ptr)->alignment);
|
||||
if ((*ptr)->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
if ((*ptr)->size > 8)
|
||||
{
|
||||
bytes += (*ptr)->size;
|
||||
bytes += sizeof (void *);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((*ptr)->size > 4)
|
||||
bytes += 8;
|
||||
else
|
||||
bytes += 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
bytes += STACK_ARG_SIZE ((*ptr)->size);
|
||||
}
|
||||
|
||||
cif->bytes = bytes;
|
||||
|
||||
return ffi_prep_cif_machdep (cif);
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep (ffi_cif * cif)
|
||||
{
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_STRUCT:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern void ffi_call_SYSV (int (*)(char *, extended_cif *),
|
||||
extended_cif *,
|
||||
unsigned, unsigned, unsigned *, void (*fn) ())
|
||||
__attribute__ ((__visibility__ ("hidden")));
|
||||
|
||||
void
|
||||
ffi_call (ffi_cif * cif, void (*fn) (), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Because the following variables are not exported outside libffi, we
|
||||
mark them hidden. */
|
||||
|
||||
/* Assembly code for the jump stub. */
|
||||
extern const char ffi_cris_trampoline_template[]
|
||||
__attribute__ ((__visibility__ ("hidden")));
|
||||
|
||||
/* Offset into ffi_cris_trampoline_template of where to put the
|
||||
ffi_prep_closure_inner function. */
|
||||
extern const int ffi_cris_trampoline_fn_offset
|
||||
__attribute__ ((__visibility__ ("hidden")));
|
||||
|
||||
/* Offset into ffi_cris_trampoline_template of where to put the
|
||||
closure data. */
|
||||
extern const int ffi_cris_trampoline_closure_offset
|
||||
__attribute__ ((__visibility__ ("hidden")));
|
||||
|
||||
/* This function is sibling-called (jumped to) by the closure
|
||||
trampoline. We get R10..R13 at PARAMS[0..3] and a copy of [SP] at
|
||||
PARAMS[4] to simplify handling of a straddling parameter. A copy
|
||||
of R9 is at PARAMS[5] and SP at PARAMS[6]. These parameters are
|
||||
put at the appropriate place in CLOSURE which is then executed and
|
||||
the return value is passed back to the caller. */
|
||||
|
||||
static unsigned long long
|
||||
ffi_prep_closure_inner (void **params, ffi_closure* closure)
|
||||
{
|
||||
char *register_args = (char *) params;
|
||||
void *struct_ret = params[5];
|
||||
char *stack_args = params[6];
|
||||
char *ptr = register_args;
|
||||
ffi_cif *cif = closure->cif;
|
||||
ffi_type **arg_types = cif->arg_types;
|
||||
|
||||
/* Max room needed is number of arguments as 64-bit values. */
|
||||
void **avalue = alloca (closure->cif->nargs * sizeof(void *));
|
||||
int i;
|
||||
int doing_regs;
|
||||
long long llret = 0;
|
||||
|
||||
/* Find the address of each argument. */
|
||||
for (i = 0, doing_regs = 1; i < cif->nargs; i++)
|
||||
{
|
||||
/* Types up to and including 8 bytes go by-value. */
|
||||
if (arg_types[i]->size <= 4)
|
||||
{
|
||||
avalue[i] = ptr;
|
||||
ptr += 4;
|
||||
}
|
||||
else if (arg_types[i]->size <= 8)
|
||||
{
|
||||
avalue[i] = ptr;
|
||||
ptr += 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
FFI_ASSERT (arg_types[i]->type == FFI_TYPE_STRUCT);
|
||||
|
||||
/* Passed by-reference, so copy the pointer. */
|
||||
avalue[i] = *(void **) ptr;
|
||||
ptr += 4;
|
||||
}
|
||||
|
||||
/* If we've handled more arguments than fit in registers, start
|
||||
looking at the those passed on the stack. Step over the
|
||||
first one if we had a straddling parameter. */
|
||||
if (doing_regs && ptr >= register_args + 4*4)
|
||||
{
|
||||
ptr = stack_args + ((ptr > register_args + 4*4) ? 4 : 0);
|
||||
doing_regs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
(closure->fun) (cif,
|
||||
|
||||
cif->rtype->type == FFI_TYPE_STRUCT
|
||||
/* The caller allocated space for the return
|
||||
structure, and passed a pointer to this space in
|
||||
R9. */
|
||||
? struct_ret
|
||||
|
||||
/* We take advantage of being able to ignore that
|
||||
the high part isn't set if the return value is
|
||||
not in R10:R11, but in R10 only. */
|
||||
: (void *) &llret,
|
||||
|
||||
avalue, closure->user_data);
|
||||
|
||||
return llret;
|
||||
}
|
||||
|
||||
/* API function: Prepare the trampoline. */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif *, void *, void **, void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
void *innerfn = ffi_prep_closure_inner;
|
||||
FFI_ASSERT (cif->abi == FFI_SYSV);
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
memcpy (closure->tramp, ffi_cris_trampoline_template,
|
||||
FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE);
|
||||
memcpy (closure->tramp + ffi_cris_trampoline_fn_offset,
|
||||
&innerfn, sizeof (void *));
|
||||
memcpy (closure->tramp + ffi_cris_trampoline_closure_offset,
|
||||
&codeloc, sizeof (void *));
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
51
src/cris/ffitarget.h
Normal file
51
src/cris/ffitarget.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for CRIS.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_SYSV,
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE 36
|
||||
#define FFI_CRIS_TRAMPOLINE_DATA_PART_SIZE (7*4)
|
||||
#define FFI_TRAMPOLINE_SIZE \
|
||||
(FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE + FFI_CRIS_TRAMPOLINE_DATA_PART_SIZE)
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
215
src/cris/sysv.S
Normal file
215
src/cris/sysv.S
Normal file
@@ -0,0 +1,215 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 2004 Simon Posnjak
|
||||
Copyright (c) 2005 Axis Communications AB
|
||||
|
||||
CRIS 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 SIMON POSNJAK 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>
|
||||
#define CONCAT(x,y) x ## y
|
||||
#define XCONCAT(x,y) CONCAT (x, y)
|
||||
#define L(x) XCONCAT (__USER_LABEL_PREFIX__, x)
|
||||
|
||||
.text
|
||||
|
||||
;; OK, when we get called we should have this (according to
|
||||
;; AXIS ETRAX 100LX Programmer's Manual chapter 6.3).
|
||||
;;
|
||||
;; R10: ffi_prep_args (func. pointer)
|
||||
;; R11: &ecif
|
||||
;; R12: cif->bytes
|
||||
;; R13: fig->flags
|
||||
;; sp+0: ecif.rvalue
|
||||
;; sp+4: fn (function pointer to the function that we need to call)
|
||||
|
||||
.globl L(ffi_call_SYSV)
|
||||
.type L(ffi_call_SYSV),@function
|
||||
.hidden L(ffi_call_SYSV)
|
||||
|
||||
L(ffi_call_SYSV):
|
||||
;; Save the regs to the stack.
|
||||
push $srp
|
||||
;; Used for stack pointer saving.
|
||||
push $r6
|
||||
;; Used for function address pointer.
|
||||
push $r7
|
||||
;; Used for stack pointer saving.
|
||||
push $r8
|
||||
;; We save fig->flags to stack we will need them after we
|
||||
;; call The Function.
|
||||
push $r13
|
||||
|
||||
;; Saving current stack pointer.
|
||||
move.d $sp,$r8
|
||||
move.d $sp,$r6
|
||||
|
||||
;; Move address of ffi_prep_args to r13.
|
||||
move.d $r10,$r13
|
||||
|
||||
;; Make room on the stack for the args of fn.
|
||||
sub.d $r12,$sp
|
||||
|
||||
;; Function void ffi_prep_args(char *stack, extended_cif *ecif) parameters are:
|
||||
;; r10 <-- stack pointer
|
||||
;; r11 <-- &ecif (already there)
|
||||
move.d $sp,$r10
|
||||
|
||||
;; Call the function.
|
||||
jsr $r13
|
||||
|
||||
;; Save the size of the structures which are passed on stack.
|
||||
move.d $r10,$r7
|
||||
|
||||
;; Move first four args in to r10..r13.
|
||||
move.d [$sp+0],$r10
|
||||
move.d [$sp+4],$r11
|
||||
move.d [$sp+8],$r12
|
||||
move.d [$sp+12],$r13
|
||||
|
||||
;; Adjust the stack and check if any parameters are given on stack.
|
||||
addq 16,$sp
|
||||
sub.d $r7,$r6
|
||||
cmp.d $sp,$r6
|
||||
|
||||
bpl go_on
|
||||
nop
|
||||
|
||||
go_on_no_params_on_stack:
|
||||
move.d $r6,$sp
|
||||
|
||||
go_on:
|
||||
;; Discover if we need to put rval address in to r9.
|
||||
move.d [$r8+0],$r7
|
||||
cmpq FFI_TYPE_STRUCT,$r7
|
||||
bne call_now
|
||||
nop
|
||||
|
||||
;; Move rval address to $r9.
|
||||
move.d [$r8+20],$r9
|
||||
|
||||
call_now:
|
||||
;; Move address of The Function in to r7.
|
||||
move.d [$r8+24],$r7
|
||||
|
||||
;; Call The Function.
|
||||
jsr $r7
|
||||
|
||||
;; Reset stack.
|
||||
move.d $r8,$sp
|
||||
|
||||
;; Load rval type (fig->flags) in to r13.
|
||||
pop $r13
|
||||
|
||||
;; Detect rval type.
|
||||
cmpq FFI_TYPE_VOID,$r13
|
||||
beq epilogue
|
||||
|
||||
cmpq FFI_TYPE_STRUCT,$r13
|
||||
beq epilogue
|
||||
|
||||
cmpq FFI_TYPE_DOUBLE,$r13
|
||||
beq return_double_or_longlong
|
||||
|
||||
cmpq FFI_TYPE_UINT64,$r13
|
||||
beq return_double_or_longlong
|
||||
|
||||
cmpq FFI_TYPE_SINT64,$r13
|
||||
beq return_double_or_longlong
|
||||
nop
|
||||
|
||||
;; Just return the 32 bit value.
|
||||
ba return
|
||||
nop
|
||||
|
||||
return_double_or_longlong:
|
||||
;; Load half of the rval to r10 and the other half to r11.
|
||||
move.d [$sp+16],$r13
|
||||
move.d $r10,[$r13]
|
||||
addq 4,$r13
|
||||
move.d $r11,[$r13]
|
||||
ba epilogue
|
||||
nop
|
||||
|
||||
return:
|
||||
;; Load the rval to r10.
|
||||
move.d [$sp+16],$r13
|
||||
move.d $r10,[$r13]
|
||||
|
||||
epilogue:
|
||||
pop $r8
|
||||
pop $r7
|
||||
pop $r6
|
||||
Jump [$sp+]
|
||||
|
||||
.size ffi_call_SYSV,.-ffi_call_SYSV
|
||||
|
||||
/* Save R10..R13 into an array, somewhat like varargs. Copy the next
|
||||
argument too, to simplify handling of any straddling parameter.
|
||||
Save R9 and SP after those. Jump to function handling the rest.
|
||||
Since this is a template, copied and the main function filled in by
|
||||
the user. */
|
||||
|
||||
.globl L(ffi_cris_trampoline_template)
|
||||
.type L(ffi_cris_trampoline_template),@function
|
||||
.hidden L(ffi_cris_trampoline_template)
|
||||
|
||||
L(ffi_cris_trampoline_template):
|
||||
0:
|
||||
/* The value we get for "PC" is right after the prefix instruction,
|
||||
two bytes from the beginning, i.e. 0b+2. */
|
||||
move.d $r10,[$pc+2f-(0b+2)]
|
||||
move.d $pc,$r10
|
||||
1:
|
||||
addq 2f-1b+4,$r10
|
||||
move.d $r11,[$r10+]
|
||||
move.d $r12,[$r10+]
|
||||
move.d $r13,[$r10+]
|
||||
move.d [$sp],$r11
|
||||
move.d $r11,[$r10+]
|
||||
move.d $r9,[$r10+]
|
||||
move.d $sp,[$r10+]
|
||||
subq FFI_CRIS_TRAMPOLINE_DATA_PART_SIZE,$r10
|
||||
move.d 0,$r11
|
||||
3:
|
||||
jump 0
|
||||
2:
|
||||
.size ffi_cris_trampoline_template,.-0b
|
||||
|
||||
/* This macro create a constant usable as "extern const int \name" in
|
||||
C from within libffi, when \name has no prefix decoration. */
|
||||
|
||||
.macro const name,value
|
||||
.globl \name
|
||||
.type \name,@object
|
||||
.hidden \name
|
||||
\name:
|
||||
.dword \value
|
||||
.size \name,4
|
||||
.endm
|
||||
|
||||
/* Constants for offsets within the trampoline. We could do this with
|
||||
just symbols, avoiding memory contents and memory accesses, but the
|
||||
C usage code would look a bit stranger. */
|
||||
|
||||
const L(ffi_cris_trampoline_fn_offset),2b-4-0b
|
||||
const L(ffi_cris_trampoline_closure_offset),3b-4-0b
|
||||
59
src/debug.c
Normal file
59
src/debug.c
Normal file
@@ -0,0 +1,59 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
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
|
||||
``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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* General debugging routines */
|
||||
|
||||
void ffi_stop_here(void)
|
||||
{
|
||||
/* This function is only useful for debugging purposes.
|
||||
Place a breakpoint on ffi_stop_here to be notified of
|
||||
significant events. */
|
||||
}
|
||||
|
||||
/* This function should only be called via the FFI_ASSERT() macro */
|
||||
|
||||
void ffi_assert(char *expr, char *file, int line)
|
||||
{
|
||||
fprintf(stderr, "ASSERTION FAILURE: %s at %s:%d\n", expr, file, line);
|
||||
ffi_stop_here();
|
||||
abort();
|
||||
}
|
||||
|
||||
/* Perform a sanity check on an ffi_type structure */
|
||||
|
||||
void ffi_type_test(ffi_type *a, char *file, int line)
|
||||
{
|
||||
FFI_ASSERT_AT(a != NULL, file, line);
|
||||
|
||||
FFI_ASSERT_AT(a->type <= FFI_TYPE_LAST, file, line);
|
||||
FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->size > 0, file, line);
|
||||
FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->alignment > 0, file, line);
|
||||
FFI_ASSERT_AT(a->type != FFI_TYPE_STRUCT || a->elements != NULL, file, line);
|
||||
|
||||
}
|
||||
5099
src/dlmalloc.c
Normal file
5099
src/dlmalloc.c
Normal file
File diff suppressed because it is too large
Load Diff
130
src/frv/.svn/entries
Normal file
130
src/frv/.svn/entries
Normal file
@@ -0,0 +1,130 @@
|
||||
10
|
||||
|
||||
dir
|
||||
152280
|
||||
svn://gcc.gnu.org/svn/gcc/trunk/libffi/src/frv
|
||||
svn://gcc.gnu.org/svn/gcc
|
||||
|
||||
|
||||
|
||||
2009-06-04T15:43:03.499507Z
|
||||
148172
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
138bc75d-0d04-0410-961f-82ee72b054a4
|
||||
|
||||
eabi.S
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-04-24T17:46:15.000000Z
|
||||
b9ecce87980cf9448d35f168d0b12575
|
||||
2007-04-13T07:21:04.913930Z
|
||||
123776
|
||||
bonzini
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
3414
|
||||
|
||||
ffitarget.h
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:02.000000Z
|
||||
7e0905257934522b5eacfc1bbf5bb459
|
||||
2009-06-04T15:11:12.475454Z
|
||||
148171
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
2066
|
||||
|
||||
ffi.c
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:02.000000Z
|
||||
cd95ee2906582020737463464ea8806b
|
||||
2009-06-04T15:43:03.499507Z
|
||||
148172
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
8448
|
||||
|
||||
128
src/frv/.svn/text-base/eabi.S.svn-base
Normal file
128
src/frv/.svn/text-base/eabi.S.svn-base
Normal file
@@ -0,0 +1,128 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
eabi.S - Copyright (c) 2004 Anthony Green
|
||||
|
||||
FR-V 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
.globl ffi_prep_args_EABI
|
||||
|
||||
.text
|
||||
.p2align 4
|
||||
.globl ffi_call_EABI
|
||||
.type ffi_call_EABI, @function
|
||||
|
||||
# gr8 : ffi_prep_args
|
||||
# gr9 : &ecif
|
||||
# gr10: cif->bytes
|
||||
# gr11: fig->flags
|
||||
# gr12: ecif.rvalue
|
||||
# gr13: fn
|
||||
|
||||
ffi_call_EABI:
|
||||
addi sp, #-80, sp
|
||||
sti fp, @(sp, #24)
|
||||
addi sp, #24, fp
|
||||
movsg lr, gr5
|
||||
|
||||
/* Make room for the new arguments. */
|
||||
/* subi sp, fp, gr10 */
|
||||
|
||||
/* Store return address and incoming args on stack. */
|
||||
sti gr5, @(fp, #8)
|
||||
sti gr8, @(fp, #-4)
|
||||
sti gr9, @(fp, #-8)
|
||||
sti gr10, @(fp, #-12)
|
||||
sti gr11, @(fp, #-16)
|
||||
sti gr12, @(fp, #-20)
|
||||
sti gr13, @(fp, #-24)
|
||||
|
||||
sub sp, gr10, sp
|
||||
|
||||
/* Call ffi_prep_args. */
|
||||
ldi @(fp, #-4), gr4
|
||||
addi sp, #0, gr8
|
||||
ldi @(fp, #-8), gr9
|
||||
#ifdef __FRV_FDPIC__
|
||||
ldd @(gr4, gr0), gr14
|
||||
calll @(gr14, gr0)
|
||||
#else
|
||||
calll @(gr4, gr0)
|
||||
#endif
|
||||
|
||||
/* ffi_prep_args returns the new stack pointer. */
|
||||
mov gr8, gr4
|
||||
|
||||
ldi @(sp, #0), gr8
|
||||
ldi @(sp, #4), gr9
|
||||
ldi @(sp, #8), gr10
|
||||
ldi @(sp, #12), gr11
|
||||
ldi @(sp, #16), gr12
|
||||
ldi @(sp, #20), gr13
|
||||
|
||||
/* Always copy the return value pointer into the hidden
|
||||
parameter register. This is only strictly necessary
|
||||
when we're returning an aggregate type, but it doesn't
|
||||
hurt to do this all the time, and it saves a branch. */
|
||||
ldi @(fp, #-20), gr3
|
||||
|
||||
/* Use the ffi_prep_args return value for the new sp. */
|
||||
mov gr4, sp
|
||||
|
||||
/* Call the target function. */
|
||||
ldi @(fp, -24), gr4
|
||||
#ifdef __FRV_FDPIC__
|
||||
ldd @(gr4, gr0), gr14
|
||||
calll @(gr14, gr0)
|
||||
#else
|
||||
calll @(gr4, gr0)
|
||||
#endif
|
||||
|
||||
/* Store the result. */
|
||||
ldi @(fp, #-16), gr10 /* fig->flags */
|
||||
ldi @(fp, #-20), gr4 /* ecif.rvalue */
|
||||
|
||||
/* Is the return value stored in two registers? */
|
||||
cmpi gr10, #8, icc0
|
||||
bne icc0, 0, .L2
|
||||
/* Yes, save them. */
|
||||
sti gr8, @(gr4, #0)
|
||||
sti gr9, @(gr4, #4)
|
||||
bra .L3
|
||||
.L2:
|
||||
/* Is the return value a structure? */
|
||||
cmpi gr10, #-1, icc0
|
||||
beq icc0, 0, .L3
|
||||
/* No, save a 4 byte return value. */
|
||||
sti gr8, @(gr4, #0)
|
||||
.L3:
|
||||
|
||||
/* Restore the stack, and return. */
|
||||
ldi @(fp, 8), gr5
|
||||
ld @(fp, gr0), fp
|
||||
addi sp,#80,sp
|
||||
jmpl @(gr5,gr0)
|
||||
.size ffi_call_EABI, .-ffi_call_EABI
|
||||
|
||||
292
src/frv/.svn/text-base/ffi.c.svn-base
Normal file
292
src/frv/.svn/text-base/ffi.c.svn-base
Normal file
@@ -0,0 +1,292 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (C) 2004 Anthony Green
|
||||
Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
Copyright (C) 2008 Red Hat, Inc.
|
||||
|
||||
FR-V 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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* 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)
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
register int count = 0;
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
argp = stack;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
(i != 0);
|
||||
i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
z = (*p_arg)->size;
|
||||
|
||||
if ((*p_arg)->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
z = sizeof(void*);
|
||||
*(void **) argp = *p_argv;
|
||||
}
|
||||
/* if ((*p_arg)->type == FFI_TYPE_FLOAT)
|
||||
{
|
||||
if (count > 24)
|
||||
{
|
||||
// This is going on the stack. Turn it into a double.
|
||||
*(double *) argp = (double) *(float*)(* p_argv);
|
||||
z = sizeof(double);
|
||||
}
|
||||
else
|
||||
*(void **) argp = *(void **)(* p_argv);
|
||||
} */
|
||||
else if (z < sizeof(int))
|
||||
{
|
||||
z = sizeof(int);
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
}
|
||||
else if (z == sizeof(int))
|
||||
{
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(argp, *p_argv, z);
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
count += z;
|
||||
}
|
||||
|
||||
return (stack + ((count > 24) ? 24 : ALIGN_DOWN(count, 8)));
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
cif->flags = -1;
|
||||
else
|
||||
cif->flags = cif->rtype->size;
|
||||
|
||||
cif->bytes = ALIGN (cif->bytes, 8);
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern void ffi_call_EABI(void *(*)(char *, extended_cif *),
|
||||
extended_cif *,
|
||||
unsigned, unsigned,
|
||||
unsigned *,
|
||||
void (*fn)(void));
|
||||
|
||||
void ffi_call(ffi_cif *cif,
|
||||
void (*fn)(void),
|
||||
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_EABI:
|
||||
ffi_call_EABI(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
|
||||
unsigned arg4, unsigned arg5, unsigned arg6)
|
||||
{
|
||||
/* This function is called by a trampoline. The trampoline stows a
|
||||
pointer to the ffi_closure object in gr7. We must save this
|
||||
pointer in a place that will persist while we do our work. */
|
||||
register ffi_closure *creg __asm__ ("gr7");
|
||||
ffi_closure *closure = creg;
|
||||
|
||||
/* Arguments that don't fit in registers are found on the stack
|
||||
at a fixed offset above the current frame pointer. */
|
||||
register char *frame_pointer __asm__ ("fp");
|
||||
char *stack_args = frame_pointer + 16;
|
||||
|
||||
/* Lay the register arguments down in a continuous chunk of memory. */
|
||||
unsigned register_args[6] =
|
||||
{ arg1, arg2, arg3, arg4, arg5, arg6 };
|
||||
|
||||
ffi_cif *cif = closure->cif;
|
||||
ffi_type **arg_types = cif->arg_types;
|
||||
void **avalue = alloca (cif->nargs * sizeof(void *));
|
||||
char *ptr = (char *) register_args;
|
||||
int i;
|
||||
|
||||
/* Find the address of each argument. */
|
||||
for (i = 0; i < cif->nargs; i++)
|
||||
{
|
||||
switch (arg_types[i]->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT8:
|
||||
avalue[i] = ptr + 3;
|
||||
break;
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
avalue[i] = ptr + 2;
|
||||
break;
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_FLOAT:
|
||||
avalue[i] = ptr;
|
||||
break;
|
||||
case FFI_TYPE_STRUCT:
|
||||
avalue[i] = *(void**)ptr;
|
||||
break;
|
||||
default:
|
||||
/* This is an 8-byte value. */
|
||||
avalue[i] = ptr;
|
||||
ptr += 4;
|
||||
break;
|
||||
}
|
||||
ptr += 4;
|
||||
|
||||
/* If we've handled more arguments than fit in registers,
|
||||
start looking at the those passed on the stack. */
|
||||
if (ptr == ((char *)register_args + (6*4)))
|
||||
ptr = stack_args;
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
/* The caller allocates space for the return structure, and
|
||||
passes a pointer to this space in gr3. Use this value directly
|
||||
as the return value. */
|
||||
register void *return_struct_ptr __asm__("gr3");
|
||||
(closure->fun) (cif, return_struct_ptr, avalue, closure->user_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocate space for the return value and call the function. */
|
||||
long long rvalue;
|
||||
(closure->fun) (cif, &rvalue, avalue, closure->user_data);
|
||||
|
||||
/* Functions return 4-byte or smaller results in gr8. 8-byte
|
||||
values also use gr9. We fill the both, even for small return
|
||||
values, just to avoid a branch. */
|
||||
asm ("ldi @(%0, #0), gr8" : : "r" (&rvalue));
|
||||
asm ("ldi @(%0, #0), gr9" : : "r" (&((int *) &rvalue)[1]));
|
||||
}
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
unsigned int *tramp = (unsigned int *) &closure->tramp[0];
|
||||
unsigned long fn = (long) ffi_closure_eabi;
|
||||
unsigned long cls = (long) codeloc;
|
||||
#ifdef __FRV_FDPIC__
|
||||
register void *got __asm__("gr15");
|
||||
#endif
|
||||
int i;
|
||||
|
||||
fn = (unsigned long) ffi_closure_eabi;
|
||||
|
||||
#ifdef __FRV_FDPIC__
|
||||
tramp[0] = &((unsigned int *)codeloc)[2];
|
||||
tramp[1] = got;
|
||||
tramp[2] = 0x8cfc0000 + (fn & 0xffff); /* setlos lo(fn), gr6 */
|
||||
tramp[3] = 0x8efc0000 + (cls & 0xffff); /* setlos lo(cls), gr7 */
|
||||
tramp[4] = 0x8cf80000 + (fn >> 16); /* sethi hi(fn), gr6 */
|
||||
tramp[5] = 0x8ef80000 + (cls >> 16); /* sethi hi(cls), gr7 */
|
||||
tramp[6] = 0x9cc86000; /* ldi @(gr6, #0), gr14 */
|
||||
tramp[7] = 0x8030e000; /* jmpl @(gr14, gr0) */
|
||||
#else
|
||||
tramp[0] = 0x8cfc0000 + (fn & 0xffff); /* setlos lo(fn), gr6 */
|
||||
tramp[1] = 0x8efc0000 + (cls & 0xffff); /* setlos lo(cls), gr7 */
|
||||
tramp[2] = 0x8cf80000 + (fn >> 16); /* sethi hi(fn), gr6 */
|
||||
tramp[3] = 0x8ef80000 + (cls >> 16); /* sethi hi(cls), gr7 */
|
||||
tramp[4] = 0x80300006; /* jmpl @(gr0, gr6) */
|
||||
#endif
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
/* Cache flushing. */
|
||||
for (i = 0; i < FFI_TRAMPOLINE_SIZE; i++)
|
||||
__asm__ volatile ("dcf @(%0,%1)\n\tici @(%2,%1)" :: "r" (tramp), "r" (i),
|
||||
"r" (codeloc));
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
61
src/frv/.svn/text-base/ffitarget.h.svn-base
Normal file
61
src/frv/.svn/text-base/ffitarget.h.svn-base
Normal file
@@ -0,0 +1,61 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2004 Red Hat, Inc.
|
||||
Target configuration macros for FR-V
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
/* ---- System specific configurations ----------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
|
||||
#ifdef FRV
|
||||
FFI_EABI,
|
||||
FFI_DEFAULT_ABI = FFI_EABI,
|
||||
#endif
|
||||
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#ifdef __FRV_FDPIC__
|
||||
/* Trampolines are 8 4-byte instructions long. */
|
||||
#define FFI_TRAMPOLINE_SIZE (8*4)
|
||||
#else
|
||||
/* Trampolines are 5 4-byte instructions long. */
|
||||
#define FFI_TRAMPOLINE_SIZE (5*4)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
128
src/frv/eabi.S
Normal file
128
src/frv/eabi.S
Normal file
@@ -0,0 +1,128 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
eabi.S - Copyright (c) 2004 Anthony Green
|
||||
|
||||
FR-V 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
.globl ffi_prep_args_EABI
|
||||
|
||||
.text
|
||||
.p2align 4
|
||||
.globl ffi_call_EABI
|
||||
.type ffi_call_EABI, @function
|
||||
|
||||
# gr8 : ffi_prep_args
|
||||
# gr9 : &ecif
|
||||
# gr10: cif->bytes
|
||||
# gr11: fig->flags
|
||||
# gr12: ecif.rvalue
|
||||
# gr13: fn
|
||||
|
||||
ffi_call_EABI:
|
||||
addi sp, #-80, sp
|
||||
sti fp, @(sp, #24)
|
||||
addi sp, #24, fp
|
||||
movsg lr, gr5
|
||||
|
||||
/* Make room for the new arguments. */
|
||||
/* subi sp, fp, gr10 */
|
||||
|
||||
/* Store return address and incoming args on stack. */
|
||||
sti gr5, @(fp, #8)
|
||||
sti gr8, @(fp, #-4)
|
||||
sti gr9, @(fp, #-8)
|
||||
sti gr10, @(fp, #-12)
|
||||
sti gr11, @(fp, #-16)
|
||||
sti gr12, @(fp, #-20)
|
||||
sti gr13, @(fp, #-24)
|
||||
|
||||
sub sp, gr10, sp
|
||||
|
||||
/* Call ffi_prep_args. */
|
||||
ldi @(fp, #-4), gr4
|
||||
addi sp, #0, gr8
|
||||
ldi @(fp, #-8), gr9
|
||||
#ifdef __FRV_FDPIC__
|
||||
ldd @(gr4, gr0), gr14
|
||||
calll @(gr14, gr0)
|
||||
#else
|
||||
calll @(gr4, gr0)
|
||||
#endif
|
||||
|
||||
/* ffi_prep_args returns the new stack pointer. */
|
||||
mov gr8, gr4
|
||||
|
||||
ldi @(sp, #0), gr8
|
||||
ldi @(sp, #4), gr9
|
||||
ldi @(sp, #8), gr10
|
||||
ldi @(sp, #12), gr11
|
||||
ldi @(sp, #16), gr12
|
||||
ldi @(sp, #20), gr13
|
||||
|
||||
/* Always copy the return value pointer into the hidden
|
||||
parameter register. This is only strictly necessary
|
||||
when we're returning an aggregate type, but it doesn't
|
||||
hurt to do this all the time, and it saves a branch. */
|
||||
ldi @(fp, #-20), gr3
|
||||
|
||||
/* Use the ffi_prep_args return value for the new sp. */
|
||||
mov gr4, sp
|
||||
|
||||
/* Call the target function. */
|
||||
ldi @(fp, -24), gr4
|
||||
#ifdef __FRV_FDPIC__
|
||||
ldd @(gr4, gr0), gr14
|
||||
calll @(gr14, gr0)
|
||||
#else
|
||||
calll @(gr4, gr0)
|
||||
#endif
|
||||
|
||||
/* Store the result. */
|
||||
ldi @(fp, #-16), gr10 /* fig->flags */
|
||||
ldi @(fp, #-20), gr4 /* ecif.rvalue */
|
||||
|
||||
/* Is the return value stored in two registers? */
|
||||
cmpi gr10, #8, icc0
|
||||
bne icc0, 0, .L2
|
||||
/* Yes, save them. */
|
||||
sti gr8, @(gr4, #0)
|
||||
sti gr9, @(gr4, #4)
|
||||
bra .L3
|
||||
.L2:
|
||||
/* Is the return value a structure? */
|
||||
cmpi gr10, #-1, icc0
|
||||
beq icc0, 0, .L3
|
||||
/* No, save a 4 byte return value. */
|
||||
sti gr8, @(gr4, #0)
|
||||
.L3:
|
||||
|
||||
/* Restore the stack, and return. */
|
||||
ldi @(fp, 8), gr5
|
||||
ld @(fp, gr0), fp
|
||||
addi sp,#80,sp
|
||||
jmpl @(gr5,gr0)
|
||||
.size ffi_call_EABI, .-ffi_call_EABI
|
||||
|
||||
292
src/frv/ffi.c
Normal file
292
src/frv/ffi.c
Normal file
@@ -0,0 +1,292 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (C) 2004 Anthony Green
|
||||
Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
Copyright (C) 2008 Red Hat, Inc.
|
||||
|
||||
FR-V 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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* 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)
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
register int count = 0;
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
argp = stack;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
(i != 0);
|
||||
i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
z = (*p_arg)->size;
|
||||
|
||||
if ((*p_arg)->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
z = sizeof(void*);
|
||||
*(void **) argp = *p_argv;
|
||||
}
|
||||
/* if ((*p_arg)->type == FFI_TYPE_FLOAT)
|
||||
{
|
||||
if (count > 24)
|
||||
{
|
||||
// This is going on the stack. Turn it into a double.
|
||||
*(double *) argp = (double) *(float*)(* p_argv);
|
||||
z = sizeof(double);
|
||||
}
|
||||
else
|
||||
*(void **) argp = *(void **)(* p_argv);
|
||||
} */
|
||||
else if (z < sizeof(int))
|
||||
{
|
||||
z = sizeof(int);
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
}
|
||||
else if (z == sizeof(int))
|
||||
{
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(argp, *p_argv, z);
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
count += z;
|
||||
}
|
||||
|
||||
return (stack + ((count > 24) ? 24 : ALIGN_DOWN(count, 8)));
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
cif->flags = -1;
|
||||
else
|
||||
cif->flags = cif->rtype->size;
|
||||
|
||||
cif->bytes = ALIGN (cif->bytes, 8);
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern void ffi_call_EABI(void *(*)(char *, extended_cif *),
|
||||
extended_cif *,
|
||||
unsigned, unsigned,
|
||||
unsigned *,
|
||||
void (*fn)(void));
|
||||
|
||||
void ffi_call(ffi_cif *cif,
|
||||
void (*fn)(void),
|
||||
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_EABI:
|
||||
ffi_call_EABI(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
|
||||
unsigned arg4, unsigned arg5, unsigned arg6)
|
||||
{
|
||||
/* This function is called by a trampoline. The trampoline stows a
|
||||
pointer to the ffi_closure object in gr7. We must save this
|
||||
pointer in a place that will persist while we do our work. */
|
||||
register ffi_closure *creg __asm__ ("gr7");
|
||||
ffi_closure *closure = creg;
|
||||
|
||||
/* Arguments that don't fit in registers are found on the stack
|
||||
at a fixed offset above the current frame pointer. */
|
||||
register char *frame_pointer __asm__ ("fp");
|
||||
char *stack_args = frame_pointer + 16;
|
||||
|
||||
/* Lay the register arguments down in a continuous chunk of memory. */
|
||||
unsigned register_args[6] =
|
||||
{ arg1, arg2, arg3, arg4, arg5, arg6 };
|
||||
|
||||
ffi_cif *cif = closure->cif;
|
||||
ffi_type **arg_types = cif->arg_types;
|
||||
void **avalue = alloca (cif->nargs * sizeof(void *));
|
||||
char *ptr = (char *) register_args;
|
||||
int i;
|
||||
|
||||
/* Find the address of each argument. */
|
||||
for (i = 0; i < cif->nargs; i++)
|
||||
{
|
||||
switch (arg_types[i]->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT8:
|
||||
avalue[i] = ptr + 3;
|
||||
break;
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
avalue[i] = ptr + 2;
|
||||
break;
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_FLOAT:
|
||||
avalue[i] = ptr;
|
||||
break;
|
||||
case FFI_TYPE_STRUCT:
|
||||
avalue[i] = *(void**)ptr;
|
||||
break;
|
||||
default:
|
||||
/* This is an 8-byte value. */
|
||||
avalue[i] = ptr;
|
||||
ptr += 4;
|
||||
break;
|
||||
}
|
||||
ptr += 4;
|
||||
|
||||
/* If we've handled more arguments than fit in registers,
|
||||
start looking at the those passed on the stack. */
|
||||
if (ptr == ((char *)register_args + (6*4)))
|
||||
ptr = stack_args;
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
/* The caller allocates space for the return structure, and
|
||||
passes a pointer to this space in gr3. Use this value directly
|
||||
as the return value. */
|
||||
register void *return_struct_ptr __asm__("gr3");
|
||||
(closure->fun) (cif, return_struct_ptr, avalue, closure->user_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocate space for the return value and call the function. */
|
||||
long long rvalue;
|
||||
(closure->fun) (cif, &rvalue, avalue, closure->user_data);
|
||||
|
||||
/* Functions return 4-byte or smaller results in gr8. 8-byte
|
||||
values also use gr9. We fill the both, even for small return
|
||||
values, just to avoid a branch. */
|
||||
asm ("ldi @(%0, #0), gr8" : : "r" (&rvalue));
|
||||
asm ("ldi @(%0, #0), gr9" : : "r" (&((int *) &rvalue)[1]));
|
||||
}
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
unsigned int *tramp = (unsigned int *) &closure->tramp[0];
|
||||
unsigned long fn = (long) ffi_closure_eabi;
|
||||
unsigned long cls = (long) codeloc;
|
||||
#ifdef __FRV_FDPIC__
|
||||
register void *got __asm__("gr15");
|
||||
#endif
|
||||
int i;
|
||||
|
||||
fn = (unsigned long) ffi_closure_eabi;
|
||||
|
||||
#ifdef __FRV_FDPIC__
|
||||
tramp[0] = &((unsigned int *)codeloc)[2];
|
||||
tramp[1] = got;
|
||||
tramp[2] = 0x8cfc0000 + (fn & 0xffff); /* setlos lo(fn), gr6 */
|
||||
tramp[3] = 0x8efc0000 + (cls & 0xffff); /* setlos lo(cls), gr7 */
|
||||
tramp[4] = 0x8cf80000 + (fn >> 16); /* sethi hi(fn), gr6 */
|
||||
tramp[5] = 0x8ef80000 + (cls >> 16); /* sethi hi(cls), gr7 */
|
||||
tramp[6] = 0x9cc86000; /* ldi @(gr6, #0), gr14 */
|
||||
tramp[7] = 0x8030e000; /* jmpl @(gr14, gr0) */
|
||||
#else
|
||||
tramp[0] = 0x8cfc0000 + (fn & 0xffff); /* setlos lo(fn), gr6 */
|
||||
tramp[1] = 0x8efc0000 + (cls & 0xffff); /* setlos lo(cls), gr7 */
|
||||
tramp[2] = 0x8cf80000 + (fn >> 16); /* sethi hi(fn), gr6 */
|
||||
tramp[3] = 0x8ef80000 + (cls >> 16); /* sethi hi(cls), gr7 */
|
||||
tramp[4] = 0x80300006; /* jmpl @(gr0, gr6) */
|
||||
#endif
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
/* Cache flushing. */
|
||||
for (i = 0; i < FFI_TRAMPOLINE_SIZE; i++)
|
||||
__asm__ volatile ("dcf @(%0,%1)\n\tici @(%2,%1)" :: "r" (tramp), "r" (i),
|
||||
"r" (codeloc));
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
61
src/frv/ffitarget.h
Normal file
61
src/frv/ffitarget.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2004 Red Hat, Inc.
|
||||
Target configuration macros for FR-V
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
/* ---- System specific configurations ----------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
|
||||
#ifdef FRV
|
||||
FFI_EABI,
|
||||
FFI_DEFAULT_ABI = FFI_EABI,
|
||||
#endif
|
||||
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#ifdef __FRV_FDPIC__
|
||||
/* Trampolines are 8 4-byte instructions long. */
|
||||
#define FFI_TRAMPOLINE_SIZE (8*4)
|
||||
#else
|
||||
/* Trampolines are 5 4-byte instructions long. */
|
||||
#define FFI_TRAMPOLINE_SIZE (5*4)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
164
src/ia64/.svn/entries
Normal file
164
src/ia64/.svn/entries
Normal file
@@ -0,0 +1,164 @@
|
||||
10
|
||||
|
||||
dir
|
||||
152280
|
||||
svn://gcc.gnu.org/svn/gcc/trunk/libffi/src/ia64
|
||||
svn://gcc.gnu.org/svn/gcc
|
||||
|
||||
|
||||
|
||||
2009-06-04T15:43:03.499507Z
|
||||
148172
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
138bc75d-0d04-0410-961f-82ee72b054a4
|
||||
|
||||
ffitarget.h
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:03.000000Z
|
||||
6705dee4ee4609cc805413bc439c20ae
|
||||
2009-06-04T15:11:12.475454Z
|
||||
148171
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1952
|
||||
|
||||
unix.S
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:03.000000Z
|
||||
8e5389d0a78a91c44ad3532ef97779da
|
||||
2009-06-04T15:43:03.499507Z
|
||||
148172
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
11649
|
||||
|
||||
ffi.c
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:03.000000Z
|
||||
7ca86e7025e65dd69d1ed227e9fe964e
|
||||
2009-06-04T15:43:03.499507Z
|
||||
148172
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
15326
|
||||
|
||||
ia64_flags.h
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:03.000000Z
|
||||
6598837388b91973b3e6193968357fdb
|
||||
2009-06-04T15:11:12.475454Z
|
||||
148171
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1949
|
||||
|
||||
580
src/ia64/.svn/text-base/ffi.c.svn-base
Normal file
580
src/ia64/.svn/text-base/ffi.c.svn-base
Normal file
@@ -0,0 +1,580 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1998, 2007, 2008 Red Hat, Inc.
|
||||
Copyright (c) 2000 Hewlett Packard Company
|
||||
|
||||
IA64 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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <float.h>
|
||||
|
||||
#include "ia64_flags.h"
|
||||
|
||||
/* A 64-bit pointer value. In LP64 mode, this is effectively a plain
|
||||
pointer. In ILP32 mode, it's a pointer that's been extended to
|
||||
64 bits by "addp4". */
|
||||
typedef void *PTR64 __attribute__((mode(DI)));
|
||||
|
||||
/* Memory image of fp register contents. This is the implementation
|
||||
specific format used by ldf.fill/stf.spill. All we care about is
|
||||
that it wants a 16 byte aligned slot. */
|
||||
typedef struct
|
||||
{
|
||||
UINT64 x[2] __attribute__((aligned(16)));
|
||||
} fpreg;
|
||||
|
||||
|
||||
/* The stack layout given to ffi_call_unix and ffi_closure_unix_inner. */
|
||||
|
||||
struct ia64_args
|
||||
{
|
||||
fpreg fp_regs[8]; /* Contents of 8 fp arg registers. */
|
||||
UINT64 gp_regs[8]; /* Contents of 8 gp arg registers. */
|
||||
UINT64 other_args[]; /* Arguments passed on stack, variable size. */
|
||||
};
|
||||
|
||||
|
||||
/* Adjust ADDR, a pointer to an 8 byte slot, to point to the low LEN bytes. */
|
||||
|
||||
static inline void *
|
||||
endian_adjust (void *addr, size_t len)
|
||||
{
|
||||
#ifdef __BIG_ENDIAN__
|
||||
return addr + (8 - len);
|
||||
#else
|
||||
return addr;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Store VALUE to ADDR in the current cpu implementation's fp spill format.
|
||||
This is a macro instead of a function, so that it works for all 3 floating
|
||||
point types without type conversions. Type conversion to long double breaks
|
||||
the denorm support. */
|
||||
|
||||
#define stf_spill(addr, value) \
|
||||
asm ("stf.spill %0 = %1%P0" : "=m" (*addr) : "f"(value));
|
||||
|
||||
/* Load a value from ADDR, which is in the current cpu implementation's
|
||||
fp spill format. As above, this must also be a macro. */
|
||||
|
||||
#define ldf_fill(result, addr) \
|
||||
asm ("ldf.fill %0 = %1%P1" : "=f"(result) : "m"(*addr));
|
||||
|
||||
/* Return the size of the C type associated with with TYPE. Which will
|
||||
be one of the FFI_IA64_TYPE_HFA_* values. */
|
||||
|
||||
static size_t
|
||||
hfa_type_size (int type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case FFI_IA64_TYPE_HFA_FLOAT:
|
||||
return sizeof(float);
|
||||
case FFI_IA64_TYPE_HFA_DOUBLE:
|
||||
return sizeof(double);
|
||||
case FFI_IA64_TYPE_HFA_LDOUBLE:
|
||||
return sizeof(__float80);
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Load from ADDR a value indicated by TYPE. Which will be one of
|
||||
the FFI_IA64_TYPE_HFA_* values. */
|
||||
|
||||
static void
|
||||
hfa_type_load (fpreg *fpaddr, int type, void *addr)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case FFI_IA64_TYPE_HFA_FLOAT:
|
||||
stf_spill (fpaddr, *(float *) addr);
|
||||
return;
|
||||
case FFI_IA64_TYPE_HFA_DOUBLE:
|
||||
stf_spill (fpaddr, *(double *) addr);
|
||||
return;
|
||||
case FFI_IA64_TYPE_HFA_LDOUBLE:
|
||||
stf_spill (fpaddr, *(__float80 *) addr);
|
||||
return;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Load VALUE into ADDR as indicated by TYPE. Which will be one of
|
||||
the FFI_IA64_TYPE_HFA_* values. */
|
||||
|
||||
static void
|
||||
hfa_type_store (int type, void *addr, fpreg *fpaddr)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case FFI_IA64_TYPE_HFA_FLOAT:
|
||||
{
|
||||
float result;
|
||||
ldf_fill (result, fpaddr);
|
||||
*(float *) addr = result;
|
||||
break;
|
||||
}
|
||||
case FFI_IA64_TYPE_HFA_DOUBLE:
|
||||
{
|
||||
double result;
|
||||
ldf_fill (result, fpaddr);
|
||||
*(double *) addr = result;
|
||||
break;
|
||||
}
|
||||
case FFI_IA64_TYPE_HFA_LDOUBLE:
|
||||
{
|
||||
__float80 result;
|
||||
ldf_fill (result, fpaddr);
|
||||
*(__float80 *) addr = result;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Is TYPE a struct containing floats, doubles, or extended doubles,
|
||||
all of the same fp type? If so, return the element type. Return
|
||||
FFI_TYPE_VOID if not. */
|
||||
|
||||
static int
|
||||
hfa_element_type (ffi_type *type, int nested)
|
||||
{
|
||||
int element = FFI_TYPE_VOID;
|
||||
|
||||
switch (type->type)
|
||||
{
|
||||
case FFI_TYPE_FLOAT:
|
||||
/* We want to return VOID for raw floating-point types, but the
|
||||
synthetic HFA type if we're nested within an aggregate. */
|
||||
if (nested)
|
||||
element = FFI_IA64_TYPE_HFA_FLOAT;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
/* Similarly. */
|
||||
if (nested)
|
||||
element = FFI_IA64_TYPE_HFA_DOUBLE;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* Similarly, except that that HFA is true for double extended,
|
||||
but not quad precision. Both have sizeof == 16, so tell the
|
||||
difference based on the precision. */
|
||||
if (LDBL_MANT_DIG == 64 && nested)
|
||||
element = FFI_IA64_TYPE_HFA_LDOUBLE;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
{
|
||||
ffi_type **ptr = &type->elements[0];
|
||||
|
||||
for (ptr = &type->elements[0]; *ptr ; ptr++)
|
||||
{
|
||||
int sub_element = hfa_element_type (*ptr, 1);
|
||||
if (sub_element == FFI_TYPE_VOID)
|
||||
return FFI_TYPE_VOID;
|
||||
|
||||
if (element == FFI_TYPE_VOID)
|
||||
element = sub_element;
|
||||
else if (element != sub_element)
|
||||
return FFI_TYPE_VOID;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return FFI_TYPE_VOID;
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
|
||||
/* Perform machine dependent cif processing. */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
int flags;
|
||||
|
||||
/* Adjust cif->bytes to include space for the bits of the ia64_args frame
|
||||
that preceeds the integer register portion. The estimate that the
|
||||
generic bits did for the argument space required is good enough for the
|
||||
integer component. */
|
||||
cif->bytes += offsetof(struct ia64_args, gp_regs[0]);
|
||||
if (cif->bytes < sizeof(struct ia64_args))
|
||||
cif->bytes = sizeof(struct ia64_args);
|
||||
|
||||
/* Set the return type flag. */
|
||||
flags = cif->rtype->type;
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* Leave FFI_TYPE_LONGDOUBLE as meaning double extended precision,
|
||||
and encode quad precision as a two-word integer structure. */
|
||||
if (LDBL_MANT_DIG != 64)
|
||||
flags = FFI_IA64_TYPE_SMALL_STRUCT | (16 << 8);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
{
|
||||
size_t size = cif->rtype->size;
|
||||
int hfa_type = hfa_element_type (cif->rtype, 0);
|
||||
|
||||
if (hfa_type != FFI_TYPE_VOID)
|
||||
{
|
||||
size_t nelts = size / hfa_type_size (hfa_type);
|
||||
if (nelts <= 8)
|
||||
flags = hfa_type | (size << 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (size <= 32)
|
||||
flags = FFI_IA64_TYPE_SMALL_STRUCT | (size << 8);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
cif->flags = flags;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern int ffi_call_unix (struct ia64_args *, PTR64, void (*)(void), UINT64);
|
||||
|
||||
void
|
||||
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
struct ia64_args *stack;
|
||||
long i, avn, gpcount, fpcount;
|
||||
ffi_type **p_arg;
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_UNIX);
|
||||
|
||||
/* If we have no spot for a return value, make one. */
|
||||
if (rvalue == NULL && cif->rtype->type != FFI_TYPE_VOID)
|
||||
rvalue = alloca (cif->rtype->size);
|
||||
|
||||
/* Allocate the stack frame. */
|
||||
stack = alloca (cif->bytes);
|
||||
|
||||
gpcount = fpcount = 0;
|
||||
avn = cif->nargs;
|
||||
for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
|
||||
{
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
stack->gp_regs[gpcount++] = *(SINT8 *)avalue[i];
|
||||
break;
|
||||
case FFI_TYPE_UINT8:
|
||||
stack->gp_regs[gpcount++] = *(UINT8 *)avalue[i];
|
||||
break;
|
||||
case FFI_TYPE_SINT16:
|
||||
stack->gp_regs[gpcount++] = *(SINT16 *)avalue[i];
|
||||
break;
|
||||
case FFI_TYPE_UINT16:
|
||||
stack->gp_regs[gpcount++] = *(UINT16 *)avalue[i];
|
||||
break;
|
||||
case FFI_TYPE_SINT32:
|
||||
stack->gp_regs[gpcount++] = *(SINT32 *)avalue[i];
|
||||
break;
|
||||
case FFI_TYPE_UINT32:
|
||||
stack->gp_regs[gpcount++] = *(UINT32 *)avalue[i];
|
||||
break;
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
stack->gp_regs[gpcount++] = *(UINT64 *)avalue[i];
|
||||
break;
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
stack->gp_regs[gpcount++] = (UINT64)(PTR64) *(void **)avalue[i];
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (gpcount < 8 && fpcount < 8)
|
||||
stf_spill (&stack->fp_regs[fpcount++], *(float *)avalue[i]);
|
||||
stack->gp_regs[gpcount++] = *(UINT32 *)avalue[i];
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
if (gpcount < 8 && fpcount < 8)
|
||||
stf_spill (&stack->fp_regs[fpcount++], *(double *)avalue[i]);
|
||||
stack->gp_regs[gpcount++] = *(UINT64 *)avalue[i];
|
||||
break;
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
if (gpcount & 1)
|
||||
gpcount++;
|
||||
if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8)
|
||||
stf_spill (&stack->fp_regs[fpcount++], *(__float80 *)avalue[i]);
|
||||
memcpy (&stack->gp_regs[gpcount], avalue[i], 16);
|
||||
gpcount += 2;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
{
|
||||
size_t size = (*p_arg)->size;
|
||||
size_t align = (*p_arg)->alignment;
|
||||
int hfa_type = hfa_element_type (*p_arg, 0);
|
||||
|
||||
FFI_ASSERT (align <= 16);
|
||||
if (align == 16 && (gpcount & 1))
|
||||
gpcount++;
|
||||
|
||||
if (hfa_type != FFI_TYPE_VOID)
|
||||
{
|
||||
size_t hfa_size = hfa_type_size (hfa_type);
|
||||
size_t offset = 0;
|
||||
size_t gp_offset = gpcount * 8;
|
||||
|
||||
while (fpcount < 8
|
||||
&& offset < size
|
||||
&& gp_offset < 8 * 8)
|
||||
{
|
||||
hfa_type_load (&stack->fp_regs[fpcount], hfa_type,
|
||||
avalue[i] + offset);
|
||||
offset += hfa_size;
|
||||
gp_offset += hfa_size;
|
||||
fpcount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy (&stack->gp_regs[gpcount], avalue[i], size);
|
||||
gpcount += (size + 7) / 8;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
ffi_call_unix (stack, rvalue, fn, cif->flags);
|
||||
}
|
||||
|
||||
/* Closures represent a pair consisting of a function pointer, and
|
||||
some user data. A closure is invoked by reinterpreting the closure
|
||||
as a function pointer, and branching to it. Thus we can make an
|
||||
interpreted function callable as a C function: We turn the
|
||||
interpreter itself, together with a pointer specifying the
|
||||
interpreted procedure, into a closure.
|
||||
|
||||
For IA64, function pointer are already pairs consisting of a code
|
||||
pointer, and a gp pointer. The latter is needed to access global
|
||||
variables. Here we set up such a pair as the first two words of
|
||||
the closure (in the "trampoline" area), but we replace the gp
|
||||
pointer with a pointer to the closure itself. We also add the real
|
||||
gp pointer to the closure. This allows the function entry code to
|
||||
both retrieve the user data, and to restire the correct gp pointer. */
|
||||
|
||||
extern void ffi_closure_unix ();
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
/* The layout of a function descriptor. A C function pointer really
|
||||
points to one of these. */
|
||||
struct ia64_fd
|
||||
{
|
||||
UINT64 code_pointer;
|
||||
UINT64 gp;
|
||||
};
|
||||
|
||||
struct ffi_ia64_trampoline_struct
|
||||
{
|
||||
UINT64 code_pointer; /* Pointer to ffi_closure_unix. */
|
||||
UINT64 fake_gp; /* Pointer to closure, installed as gp. */
|
||||
UINT64 real_gp; /* Real gp value. */
|
||||
};
|
||||
|
||||
struct ffi_ia64_trampoline_struct *tramp;
|
||||
struct ia64_fd *fd;
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_UNIX);
|
||||
|
||||
tramp = (struct ffi_ia64_trampoline_struct *)closure->tramp;
|
||||
fd = (struct ia64_fd *)(void *)ffi_closure_unix;
|
||||
|
||||
tramp->code_pointer = fd->code_pointer;
|
||||
tramp->real_gp = fd->gp;
|
||||
tramp->fake_gp = (UINT64)(PTR64)codeloc;
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
|
||||
UINT64
|
||||
ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack,
|
||||
void *rvalue, void *r8)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
void **avalue;
|
||||
ffi_type **p_arg;
|
||||
long i, avn, gpcount, fpcount;
|
||||
|
||||
cif = closure->cif;
|
||||
avn = cif->nargs;
|
||||
avalue = alloca (avn * sizeof (void *));
|
||||
|
||||
/* If the structure return value is passed in memory get that location
|
||||
from r8 so as to pass the value directly back to the caller. */
|
||||
if (cif->flags == FFI_TYPE_STRUCT)
|
||||
rvalue = r8;
|
||||
|
||||
gpcount = fpcount = 0;
|
||||
for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
|
||||
{
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT8:
|
||||
avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 1);
|
||||
break;
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 2);
|
||||
break;
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 4);
|
||||
break;
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
avalue[i] = &stack->gp_regs[gpcount++];
|
||||
break;
|
||||
case FFI_TYPE_POINTER:
|
||||
avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], sizeof(void*));
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (gpcount < 8 && fpcount < 8)
|
||||
{
|
||||
fpreg *addr = &stack->fp_regs[fpcount++];
|
||||
float result;
|
||||
avalue[i] = addr;
|
||||
ldf_fill (result, addr);
|
||||
*(float *)addr = result;
|
||||
}
|
||||
else
|
||||
avalue[i] = endian_adjust(&stack->gp_regs[gpcount], 4);
|
||||
gpcount++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
if (gpcount < 8 && fpcount < 8)
|
||||
{
|
||||
fpreg *addr = &stack->fp_regs[fpcount++];
|
||||
double result;
|
||||
avalue[i] = addr;
|
||||
ldf_fill (result, addr);
|
||||
*(double *)addr = result;
|
||||
}
|
||||
else
|
||||
avalue[i] = &stack->gp_regs[gpcount];
|
||||
gpcount++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
if (gpcount & 1)
|
||||
gpcount++;
|
||||
if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8)
|
||||
{
|
||||
fpreg *addr = &stack->fp_regs[fpcount++];
|
||||
__float80 result;
|
||||
avalue[i] = addr;
|
||||
ldf_fill (result, addr);
|
||||
*(__float80 *)addr = result;
|
||||
}
|
||||
else
|
||||
avalue[i] = &stack->gp_regs[gpcount];
|
||||
gpcount += 2;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
{
|
||||
size_t size = (*p_arg)->size;
|
||||
size_t align = (*p_arg)->alignment;
|
||||
int hfa_type = hfa_element_type (*p_arg, 0);
|
||||
|
||||
FFI_ASSERT (align <= 16);
|
||||
if (align == 16 && (gpcount & 1))
|
||||
gpcount++;
|
||||
|
||||
if (hfa_type != FFI_TYPE_VOID)
|
||||
{
|
||||
size_t hfa_size = hfa_type_size (hfa_type);
|
||||
size_t offset = 0;
|
||||
size_t gp_offset = gpcount * 8;
|
||||
void *addr = alloca (size);
|
||||
|
||||
avalue[i] = addr;
|
||||
|
||||
while (fpcount < 8
|
||||
&& offset < size
|
||||
&& gp_offset < 8 * 8)
|
||||
{
|
||||
hfa_type_store (hfa_type, addr + offset,
|
||||
&stack->fp_regs[fpcount]);
|
||||
offset += hfa_size;
|
||||
gp_offset += hfa_size;
|
||||
fpcount += 1;
|
||||
}
|
||||
|
||||
if (offset < size)
|
||||
memcpy (addr + offset, (char *)stack->gp_regs + gp_offset,
|
||||
size - offset);
|
||||
}
|
||||
else
|
||||
avalue[i] = &stack->gp_regs[gpcount];
|
||||
|
||||
gpcount += (size + 7) / 8;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
closure->fun (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
return cif->flags;
|
||||
}
|
||||
50
src/ia64/.svn/text-base/ffitarget.h.svn-base
Normal file
50
src/ia64/.svn/text-base/ffitarget.h.svn-base
Normal file
@@ -0,0 +1,50 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for IA-64.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long long ffi_arg;
|
||||
typedef signed long long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_UNIX, /* Linux and all Unix variants use the same conventions */
|
||||
FFI_DEFAULT_ABI = FFI_UNIX,
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 24 /* Really the following struct, which */
|
||||
/* can be interpreted as a C function */
|
||||
/* descriptor: */
|
||||
|
||||
#endif
|
||||
|
||||
40
src/ia64/.svn/text-base/ia64_flags.h.svn-base
Normal file
40
src/ia64/.svn/text-base/ia64_flags.h.svn-base
Normal file
@@ -0,0 +1,40 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ia64_flags.h - Copyright (c) 2000 Hewlett Packard Company
|
||||
|
||||
IA64/unix Foreign Function Interface
|
||||
|
||||
Original author: Hans Boehm, HP Labs
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
/* "Type" codes used between assembly and C. When used as a part of
|
||||
a cfi->flags value, the low byte will be these extra type codes,
|
||||
and bits 8-31 will be the actual size of the type. */
|
||||
|
||||
/* Small structures containing N words in integer registers. */
|
||||
#define FFI_IA64_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 1)
|
||||
|
||||
/* Homogeneous Floating Point Aggregates (HFAs) which are returned
|
||||
in FP registers. */
|
||||
#define FFI_IA64_TYPE_HFA_FLOAT (FFI_TYPE_LAST + 2)
|
||||
#define FFI_IA64_TYPE_HFA_DOUBLE (FFI_TYPE_LAST + 3)
|
||||
#define FFI_IA64_TYPE_HFA_LDOUBLE (FFI_TYPE_LAST + 4)
|
||||
560
src/ia64/.svn/text-base/unix.S.svn-base
Normal file
560
src/ia64/.svn/text-base/unix.S.svn-base
Normal file
@@ -0,0 +1,560 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
unix.S - Copyright (c) 1998, 2008 Red Hat, Inc.
|
||||
Copyright (c) 2000 Hewlett Packard Company
|
||||
|
||||
IA64/unix Foreign Function Interface
|
||||
|
||||
Primary author: Hans Boehm, HP Labs
|
||||
|
||||
Loosely modeled on Cygnus code for other platforms.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#include "ia64_flags.h"
|
||||
|
||||
.pred.safe_across_calls p1-p5,p16-p63
|
||||
.text
|
||||
|
||||
/* int ffi_call_unix (struct ia64_args *stack, PTR64 rvalue,
|
||||
void (*fn)(void), int flags);
|
||||
*/
|
||||
|
||||
.align 16
|
||||
.global ffi_call_unix
|
||||
.proc ffi_call_unix
|
||||
ffi_call_unix:
|
||||
.prologue
|
||||
/* Bit o trickiness. We actually share a stack frame with ffi_call.
|
||||
Rely on the fact that ffi_call uses a vframe and don't bother
|
||||
tracking one here at all. */
|
||||
.fframe 0
|
||||
.save ar.pfs, r36 // loc0
|
||||
alloc loc0 = ar.pfs, 4, 3, 8, 0
|
||||
.save rp, loc1
|
||||
mov loc1 = b0
|
||||
.body
|
||||
add r16 = 16, in0
|
||||
mov loc2 = gp
|
||||
mov r8 = in1
|
||||
;;
|
||||
|
||||
/* Load up all of the argument registers. */
|
||||
ldf.fill f8 = [in0], 32
|
||||
ldf.fill f9 = [r16], 32
|
||||
;;
|
||||
ldf.fill f10 = [in0], 32
|
||||
ldf.fill f11 = [r16], 32
|
||||
;;
|
||||
ldf.fill f12 = [in0], 32
|
||||
ldf.fill f13 = [r16], 32
|
||||
;;
|
||||
ldf.fill f14 = [in0], 32
|
||||
ldf.fill f15 = [r16], 24
|
||||
;;
|
||||
ld8 out0 = [in0], 16
|
||||
ld8 out1 = [r16], 16
|
||||
;;
|
||||
ld8 out2 = [in0], 16
|
||||
ld8 out3 = [r16], 16
|
||||
;;
|
||||
ld8 out4 = [in0], 16
|
||||
ld8 out5 = [r16], 16
|
||||
;;
|
||||
ld8 out6 = [in0]
|
||||
ld8 out7 = [r16]
|
||||
;;
|
||||
|
||||
/* Deallocate the register save area from the stack frame. */
|
||||
mov sp = in0
|
||||
|
||||
/* Call the target function. */
|
||||
ld8 r16 = [in2], 8
|
||||
;;
|
||||
ld8 gp = [in2]
|
||||
mov b6 = r16
|
||||
br.call.sptk.many b0 = b6
|
||||
;;
|
||||
|
||||
/* Dispatch to handle return value. */
|
||||
mov gp = loc2
|
||||
zxt1 r16 = in3
|
||||
;;
|
||||
mov ar.pfs = loc0
|
||||
addl r18 = @ltoffx(.Lst_table), gp
|
||||
;;
|
||||
ld8.mov r18 = [r18], .Lst_table
|
||||
mov b0 = loc1
|
||||
;;
|
||||
shladd r18 = r16, 3, r18
|
||||
;;
|
||||
ld8 r17 = [r18]
|
||||
shr in3 = in3, 8
|
||||
;;
|
||||
add r17 = r17, r18
|
||||
;;
|
||||
mov b6 = r17
|
||||
br b6
|
||||
;;
|
||||
|
||||
.Lst_void:
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_uint8:
|
||||
zxt1 r8 = r8
|
||||
;;
|
||||
st8 [in1] = r8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_sint8:
|
||||
sxt1 r8 = r8
|
||||
;;
|
||||
st8 [in1] = r8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_uint16:
|
||||
zxt2 r8 = r8
|
||||
;;
|
||||
st8 [in1] = r8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_sint16:
|
||||
sxt2 r8 = r8
|
||||
;;
|
||||
st8 [in1] = r8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_uint32:
|
||||
zxt4 r8 = r8
|
||||
;;
|
||||
st8 [in1] = r8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_sint32:
|
||||
sxt4 r8 = r8
|
||||
;;
|
||||
st8 [in1] = r8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_int64:
|
||||
st8 [in1] = r8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_float:
|
||||
stfs [in1] = f8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_double:
|
||||
stfd [in1] = f8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_ldouble:
|
||||
stfe [in1] = f8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.Lst_small_struct:
|
||||
add sp = -16, sp
|
||||
cmp.lt p6, p0 = 8, in3
|
||||
cmp.lt p7, p0 = 16, in3
|
||||
cmp.lt p8, p0 = 24, in3
|
||||
;;
|
||||
add r16 = 8, sp
|
||||
add r17 = 16, sp
|
||||
add r18 = 24, sp
|
||||
;;
|
||||
st8 [sp] = r8
|
||||
(p6) st8 [r16] = r9
|
||||
mov out0 = in1
|
||||
(p7) st8 [r17] = r10
|
||||
(p8) st8 [r18] = r11
|
||||
mov out1 = sp
|
||||
mov out2 = in3
|
||||
br.call.sptk.many b0 = memcpy#
|
||||
;;
|
||||
mov ar.pfs = loc0
|
||||
mov b0 = loc1
|
||||
mov gp = loc2
|
||||
br.ret.sptk.many b0
|
||||
|
||||
.Lst_hfa_float:
|
||||
add r16 = 4, in1
|
||||
cmp.lt p6, p0 = 4, in3
|
||||
;;
|
||||
stfs [in1] = f8, 8
|
||||
(p6) stfs [r16] = f9, 8
|
||||
cmp.lt p7, p0 = 8, in3
|
||||
cmp.lt p8, p0 = 12, in3
|
||||
;;
|
||||
(p7) stfs [in1] = f10, 8
|
||||
(p8) stfs [r16] = f11, 8
|
||||
cmp.lt p9, p0 = 16, in3
|
||||
cmp.lt p10, p0 = 20, in3
|
||||
;;
|
||||
(p9) stfs [in1] = f12, 8
|
||||
(p10) stfs [r16] = f13, 8
|
||||
cmp.lt p6, p0 = 24, in3
|
||||
cmp.lt p7, p0 = 28, in3
|
||||
;;
|
||||
(p6) stfs [in1] = f14
|
||||
(p7) stfs [r16] = f15
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.Lst_hfa_double:
|
||||
add r16 = 8, in1
|
||||
cmp.lt p6, p0 = 8, in3
|
||||
;;
|
||||
stfd [in1] = f8, 16
|
||||
(p6) stfd [r16] = f9, 16
|
||||
cmp.lt p7, p0 = 16, in3
|
||||
cmp.lt p8, p0 = 24, in3
|
||||
;;
|
||||
(p7) stfd [in1] = f10, 16
|
||||
(p8) stfd [r16] = f11, 16
|
||||
cmp.lt p9, p0 = 32, in3
|
||||
cmp.lt p10, p0 = 40, in3
|
||||
;;
|
||||
(p9) stfd [in1] = f12, 16
|
||||
(p10) stfd [r16] = f13, 16
|
||||
cmp.lt p6, p0 = 48, in3
|
||||
cmp.lt p7, p0 = 56, in3
|
||||
;;
|
||||
(p6) stfd [in1] = f14
|
||||
(p7) stfd [r16] = f15
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.Lst_hfa_ldouble:
|
||||
add r16 = 16, in1
|
||||
cmp.lt p6, p0 = 16, in3
|
||||
;;
|
||||
stfe [in1] = f8, 32
|
||||
(p6) stfe [r16] = f9, 32
|
||||
cmp.lt p7, p0 = 32, in3
|
||||
cmp.lt p8, p0 = 48, in3
|
||||
;;
|
||||
(p7) stfe [in1] = f10, 32
|
||||
(p8) stfe [r16] = f11, 32
|
||||
cmp.lt p9, p0 = 64, in3
|
||||
cmp.lt p10, p0 = 80, in3
|
||||
;;
|
||||
(p9) stfe [in1] = f12, 32
|
||||
(p10) stfe [r16] = f13, 32
|
||||
cmp.lt p6, p0 = 96, in3
|
||||
cmp.lt p7, p0 = 112, in3
|
||||
;;
|
||||
(p6) stfe [in1] = f14
|
||||
(p7) stfe [r16] = f15
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.endp ffi_call_unix
|
||||
|
||||
.align 16
|
||||
.global ffi_closure_unix
|
||||
.proc ffi_closure_unix
|
||||
|
||||
#define FRAME_SIZE (8*16 + 8*8 + 8*16)
|
||||
|
||||
ffi_closure_unix:
|
||||
.prologue
|
||||
.save ar.pfs, r40 // loc0
|
||||
alloc loc0 = ar.pfs, 8, 4, 4, 0
|
||||
.fframe FRAME_SIZE
|
||||
add r12 = -FRAME_SIZE, r12
|
||||
.save rp, loc1
|
||||
mov loc1 = b0
|
||||
.save ar.unat, loc2
|
||||
mov loc2 = ar.unat
|
||||
.body
|
||||
|
||||
/* Retrieve closure pointer and real gp. */
|
||||
#ifdef _ILP32
|
||||
addp4 out0 = 0, gp
|
||||
addp4 gp = 16, gp
|
||||
#else
|
||||
mov out0 = gp
|
||||
add gp = 16, gp
|
||||
#endif
|
||||
;;
|
||||
ld8 gp = [gp]
|
||||
|
||||
/* Spill all of the possible argument registers. */
|
||||
add r16 = 16 + 8*16, sp
|
||||
add r17 = 16 + 8*16 + 16, sp
|
||||
;;
|
||||
stf.spill [r16] = f8, 32
|
||||
stf.spill [r17] = f9, 32
|
||||
mov loc3 = gp
|
||||
;;
|
||||
stf.spill [r16] = f10, 32
|
||||
stf.spill [r17] = f11, 32
|
||||
;;
|
||||
stf.spill [r16] = f12, 32
|
||||
stf.spill [r17] = f13, 32
|
||||
;;
|
||||
stf.spill [r16] = f14, 32
|
||||
stf.spill [r17] = f15, 24
|
||||
;;
|
||||
.mem.offset 0, 0
|
||||
st8.spill [r16] = in0, 16
|
||||
.mem.offset 8, 0
|
||||
st8.spill [r17] = in1, 16
|
||||
add out1 = 16 + 8*16, sp
|
||||
;;
|
||||
.mem.offset 0, 0
|
||||
st8.spill [r16] = in2, 16
|
||||
.mem.offset 8, 0
|
||||
st8.spill [r17] = in3, 16
|
||||
add out2 = 16, sp
|
||||
;;
|
||||
.mem.offset 0, 0
|
||||
st8.spill [r16] = in4, 16
|
||||
.mem.offset 8, 0
|
||||
st8.spill [r17] = in5, 16
|
||||
mov out3 = r8
|
||||
;;
|
||||
.mem.offset 0, 0
|
||||
st8.spill [r16] = in6
|
||||
.mem.offset 8, 0
|
||||
st8.spill [r17] = in7
|
||||
|
||||
/* Invoke ffi_closure_unix_inner for the hard work. */
|
||||
br.call.sptk.many b0 = ffi_closure_unix_inner
|
||||
;;
|
||||
|
||||
/* Dispatch to handle return value. */
|
||||
mov gp = loc3
|
||||
zxt1 r16 = r8
|
||||
;;
|
||||
addl r18 = @ltoffx(.Lld_table), gp
|
||||
mov ar.pfs = loc0
|
||||
;;
|
||||
ld8.mov r18 = [r18], .Lld_table
|
||||
mov b0 = loc1
|
||||
;;
|
||||
shladd r18 = r16, 3, r18
|
||||
mov ar.unat = loc2
|
||||
;;
|
||||
ld8 r17 = [r18]
|
||||
shr r8 = r8, 8
|
||||
;;
|
||||
add r17 = r17, r18
|
||||
add r16 = 16, sp
|
||||
;;
|
||||
mov b6 = r17
|
||||
br b6
|
||||
;;
|
||||
.label_state 1
|
||||
|
||||
.Lld_void:
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lld_int:
|
||||
.body
|
||||
.copy_state 1
|
||||
ld8 r8 = [r16]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lld_float:
|
||||
.body
|
||||
.copy_state 1
|
||||
ldfs f8 = [r16]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lld_double:
|
||||
.body
|
||||
.copy_state 1
|
||||
ldfd f8 = [r16]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lld_ldouble:
|
||||
.body
|
||||
.copy_state 1
|
||||
ldfe f8 = [r16]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.Lld_small_struct:
|
||||
.body
|
||||
.copy_state 1
|
||||
add r17 = 8, r16
|
||||
cmp.lt p6, p0 = 8, r8
|
||||
cmp.lt p7, p0 = 16, r8
|
||||
cmp.lt p8, p0 = 24, r8
|
||||
;;
|
||||
ld8 r8 = [r16], 16
|
||||
(p6) ld8 r9 = [r17], 16
|
||||
;;
|
||||
(p7) ld8 r10 = [r16]
|
||||
(p8) ld8 r11 = [r17]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.Lld_hfa_float:
|
||||
.body
|
||||
.copy_state 1
|
||||
add r17 = 4, r16
|
||||
cmp.lt p6, p0 = 4, r8
|
||||
;;
|
||||
ldfs f8 = [r16], 8
|
||||
(p6) ldfs f9 = [r17], 8
|
||||
cmp.lt p7, p0 = 8, r8
|
||||
cmp.lt p8, p0 = 12, r8
|
||||
;;
|
||||
(p7) ldfs f10 = [r16], 8
|
||||
(p8) ldfs f11 = [r17], 8
|
||||
cmp.lt p9, p0 = 16, r8
|
||||
cmp.lt p10, p0 = 20, r8
|
||||
;;
|
||||
(p9) ldfs f12 = [r16], 8
|
||||
(p10) ldfs f13 = [r17], 8
|
||||
cmp.lt p6, p0 = 24, r8
|
||||
cmp.lt p7, p0 = 28, r8
|
||||
;;
|
||||
(p6) ldfs f14 = [r16]
|
||||
(p7) ldfs f15 = [r17]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.Lld_hfa_double:
|
||||
.body
|
||||
.copy_state 1
|
||||
add r17 = 8, r16
|
||||
cmp.lt p6, p0 = 8, r8
|
||||
;;
|
||||
ldfd f8 = [r16], 16
|
||||
(p6) ldfd f9 = [r17], 16
|
||||
cmp.lt p7, p0 = 16, r8
|
||||
cmp.lt p8, p0 = 24, r8
|
||||
;;
|
||||
(p7) ldfd f10 = [r16], 16
|
||||
(p8) ldfd f11 = [r17], 16
|
||||
cmp.lt p9, p0 = 32, r8
|
||||
cmp.lt p10, p0 = 40, r8
|
||||
;;
|
||||
(p9) ldfd f12 = [r16], 16
|
||||
(p10) ldfd f13 = [r17], 16
|
||||
cmp.lt p6, p0 = 48, r8
|
||||
cmp.lt p7, p0 = 56, r8
|
||||
;;
|
||||
(p6) ldfd f14 = [r16]
|
||||
(p7) ldfd f15 = [r17]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.Lld_hfa_ldouble:
|
||||
.body
|
||||
.copy_state 1
|
||||
add r17 = 16, r16
|
||||
cmp.lt p6, p0 = 16, r8
|
||||
;;
|
||||
ldfe f8 = [r16], 32
|
||||
(p6) ldfe f9 = [r17], 32
|
||||
cmp.lt p7, p0 = 32, r8
|
||||
cmp.lt p8, p0 = 48, r8
|
||||
;;
|
||||
(p7) ldfe f10 = [r16], 32
|
||||
(p8) ldfe f11 = [r17], 32
|
||||
cmp.lt p9, p0 = 64, r8
|
||||
cmp.lt p10, p0 = 80, r8
|
||||
;;
|
||||
(p9) ldfe f12 = [r16], 32
|
||||
(p10) ldfe f13 = [r17], 32
|
||||
cmp.lt p6, p0 = 96, r8
|
||||
cmp.lt p7, p0 = 112, r8
|
||||
;;
|
||||
(p6) ldfe f14 = [r16]
|
||||
(p7) ldfe f15 = [r17]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.endp ffi_closure_unix
|
||||
|
||||
.section .rodata
|
||||
.align 8
|
||||
.Lst_table:
|
||||
data8 @pcrel(.Lst_void) // FFI_TYPE_VOID
|
||||
data8 @pcrel(.Lst_sint32) // FFI_TYPE_INT
|
||||
data8 @pcrel(.Lst_float) // FFI_TYPE_FLOAT
|
||||
data8 @pcrel(.Lst_double) // FFI_TYPE_DOUBLE
|
||||
data8 @pcrel(.Lst_ldouble) // FFI_TYPE_LONGDOUBLE
|
||||
data8 @pcrel(.Lst_uint8) // FFI_TYPE_UINT8
|
||||
data8 @pcrel(.Lst_sint8) // FFI_TYPE_SINT8
|
||||
data8 @pcrel(.Lst_uint16) // FFI_TYPE_UINT16
|
||||
data8 @pcrel(.Lst_sint16) // FFI_TYPE_SINT16
|
||||
data8 @pcrel(.Lst_uint32) // FFI_TYPE_UINT32
|
||||
data8 @pcrel(.Lst_sint32) // FFI_TYPE_SINT32
|
||||
data8 @pcrel(.Lst_int64) // FFI_TYPE_UINT64
|
||||
data8 @pcrel(.Lst_int64) // FFI_TYPE_SINT64
|
||||
data8 @pcrel(.Lst_void) // FFI_TYPE_STRUCT
|
||||
data8 @pcrel(.Lst_int64) // FFI_TYPE_POINTER
|
||||
data8 @pcrel(.Lst_small_struct) // FFI_IA64_TYPE_SMALL_STRUCT
|
||||
data8 @pcrel(.Lst_hfa_float) // FFI_IA64_TYPE_HFA_FLOAT
|
||||
data8 @pcrel(.Lst_hfa_double) // FFI_IA64_TYPE_HFA_DOUBLE
|
||||
data8 @pcrel(.Lst_hfa_ldouble) // FFI_IA64_TYPE_HFA_LDOUBLE
|
||||
|
||||
.Lld_table:
|
||||
data8 @pcrel(.Lld_void) // FFI_TYPE_VOID
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_INT
|
||||
data8 @pcrel(.Lld_float) // FFI_TYPE_FLOAT
|
||||
data8 @pcrel(.Lld_double) // FFI_TYPE_DOUBLE
|
||||
data8 @pcrel(.Lld_ldouble) // FFI_TYPE_LONGDOUBLE
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_UINT8
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_SINT8
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_UINT16
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_SINT16
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_UINT32
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_SINT32
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_UINT64
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_SINT64
|
||||
data8 @pcrel(.Lld_void) // FFI_TYPE_STRUCT
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_POINTER
|
||||
data8 @pcrel(.Lld_small_struct) // FFI_IA64_TYPE_SMALL_STRUCT
|
||||
data8 @pcrel(.Lld_hfa_float) // FFI_IA64_TYPE_HFA_FLOAT
|
||||
data8 @pcrel(.Lld_hfa_double) // FFI_IA64_TYPE_HFA_DOUBLE
|
||||
data8 @pcrel(.Lld_hfa_ldouble) // FFI_IA64_TYPE_HFA_LDOUBLE
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
580
src/ia64/ffi.c
Normal file
580
src/ia64/ffi.c
Normal file
@@ -0,0 +1,580 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1998, 2007, 2008 Red Hat, Inc.
|
||||
Copyright (c) 2000 Hewlett Packard Company
|
||||
|
||||
IA64 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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <float.h>
|
||||
|
||||
#include "ia64_flags.h"
|
||||
|
||||
/* A 64-bit pointer value. In LP64 mode, this is effectively a plain
|
||||
pointer. In ILP32 mode, it's a pointer that's been extended to
|
||||
64 bits by "addp4". */
|
||||
typedef void *PTR64 __attribute__((mode(DI)));
|
||||
|
||||
/* Memory image of fp register contents. This is the implementation
|
||||
specific format used by ldf.fill/stf.spill. All we care about is
|
||||
that it wants a 16 byte aligned slot. */
|
||||
typedef struct
|
||||
{
|
||||
UINT64 x[2] __attribute__((aligned(16)));
|
||||
} fpreg;
|
||||
|
||||
|
||||
/* The stack layout given to ffi_call_unix and ffi_closure_unix_inner. */
|
||||
|
||||
struct ia64_args
|
||||
{
|
||||
fpreg fp_regs[8]; /* Contents of 8 fp arg registers. */
|
||||
UINT64 gp_regs[8]; /* Contents of 8 gp arg registers. */
|
||||
UINT64 other_args[]; /* Arguments passed on stack, variable size. */
|
||||
};
|
||||
|
||||
|
||||
/* Adjust ADDR, a pointer to an 8 byte slot, to point to the low LEN bytes. */
|
||||
|
||||
static inline void *
|
||||
endian_adjust (void *addr, size_t len)
|
||||
{
|
||||
#ifdef __BIG_ENDIAN__
|
||||
return addr + (8 - len);
|
||||
#else
|
||||
return addr;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Store VALUE to ADDR in the current cpu implementation's fp spill format.
|
||||
This is a macro instead of a function, so that it works for all 3 floating
|
||||
point types without type conversions. Type conversion to long double breaks
|
||||
the denorm support. */
|
||||
|
||||
#define stf_spill(addr, value) \
|
||||
asm ("stf.spill %0 = %1%P0" : "=m" (*addr) : "f"(value));
|
||||
|
||||
/* Load a value from ADDR, which is in the current cpu implementation's
|
||||
fp spill format. As above, this must also be a macro. */
|
||||
|
||||
#define ldf_fill(result, addr) \
|
||||
asm ("ldf.fill %0 = %1%P1" : "=f"(result) : "m"(*addr));
|
||||
|
||||
/* Return the size of the C type associated with with TYPE. Which will
|
||||
be one of the FFI_IA64_TYPE_HFA_* values. */
|
||||
|
||||
static size_t
|
||||
hfa_type_size (int type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case FFI_IA64_TYPE_HFA_FLOAT:
|
||||
return sizeof(float);
|
||||
case FFI_IA64_TYPE_HFA_DOUBLE:
|
||||
return sizeof(double);
|
||||
case FFI_IA64_TYPE_HFA_LDOUBLE:
|
||||
return sizeof(__float80);
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Load from ADDR a value indicated by TYPE. Which will be one of
|
||||
the FFI_IA64_TYPE_HFA_* values. */
|
||||
|
||||
static void
|
||||
hfa_type_load (fpreg *fpaddr, int type, void *addr)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case FFI_IA64_TYPE_HFA_FLOAT:
|
||||
stf_spill (fpaddr, *(float *) addr);
|
||||
return;
|
||||
case FFI_IA64_TYPE_HFA_DOUBLE:
|
||||
stf_spill (fpaddr, *(double *) addr);
|
||||
return;
|
||||
case FFI_IA64_TYPE_HFA_LDOUBLE:
|
||||
stf_spill (fpaddr, *(__float80 *) addr);
|
||||
return;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Load VALUE into ADDR as indicated by TYPE. Which will be one of
|
||||
the FFI_IA64_TYPE_HFA_* values. */
|
||||
|
||||
static void
|
||||
hfa_type_store (int type, void *addr, fpreg *fpaddr)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case FFI_IA64_TYPE_HFA_FLOAT:
|
||||
{
|
||||
float result;
|
||||
ldf_fill (result, fpaddr);
|
||||
*(float *) addr = result;
|
||||
break;
|
||||
}
|
||||
case FFI_IA64_TYPE_HFA_DOUBLE:
|
||||
{
|
||||
double result;
|
||||
ldf_fill (result, fpaddr);
|
||||
*(double *) addr = result;
|
||||
break;
|
||||
}
|
||||
case FFI_IA64_TYPE_HFA_LDOUBLE:
|
||||
{
|
||||
__float80 result;
|
||||
ldf_fill (result, fpaddr);
|
||||
*(__float80 *) addr = result;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Is TYPE a struct containing floats, doubles, or extended doubles,
|
||||
all of the same fp type? If so, return the element type. Return
|
||||
FFI_TYPE_VOID if not. */
|
||||
|
||||
static int
|
||||
hfa_element_type (ffi_type *type, int nested)
|
||||
{
|
||||
int element = FFI_TYPE_VOID;
|
||||
|
||||
switch (type->type)
|
||||
{
|
||||
case FFI_TYPE_FLOAT:
|
||||
/* We want to return VOID for raw floating-point types, but the
|
||||
synthetic HFA type if we're nested within an aggregate. */
|
||||
if (nested)
|
||||
element = FFI_IA64_TYPE_HFA_FLOAT;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
/* Similarly. */
|
||||
if (nested)
|
||||
element = FFI_IA64_TYPE_HFA_DOUBLE;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* Similarly, except that that HFA is true for double extended,
|
||||
but not quad precision. Both have sizeof == 16, so tell the
|
||||
difference based on the precision. */
|
||||
if (LDBL_MANT_DIG == 64 && nested)
|
||||
element = FFI_IA64_TYPE_HFA_LDOUBLE;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
{
|
||||
ffi_type **ptr = &type->elements[0];
|
||||
|
||||
for (ptr = &type->elements[0]; *ptr ; ptr++)
|
||||
{
|
||||
int sub_element = hfa_element_type (*ptr, 1);
|
||||
if (sub_element == FFI_TYPE_VOID)
|
||||
return FFI_TYPE_VOID;
|
||||
|
||||
if (element == FFI_TYPE_VOID)
|
||||
element = sub_element;
|
||||
else if (element != sub_element)
|
||||
return FFI_TYPE_VOID;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return FFI_TYPE_VOID;
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
|
||||
/* Perform machine dependent cif processing. */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
int flags;
|
||||
|
||||
/* Adjust cif->bytes to include space for the bits of the ia64_args frame
|
||||
that preceeds the integer register portion. The estimate that the
|
||||
generic bits did for the argument space required is good enough for the
|
||||
integer component. */
|
||||
cif->bytes += offsetof(struct ia64_args, gp_regs[0]);
|
||||
if (cif->bytes < sizeof(struct ia64_args))
|
||||
cif->bytes = sizeof(struct ia64_args);
|
||||
|
||||
/* Set the return type flag. */
|
||||
flags = cif->rtype->type;
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* Leave FFI_TYPE_LONGDOUBLE as meaning double extended precision,
|
||||
and encode quad precision as a two-word integer structure. */
|
||||
if (LDBL_MANT_DIG != 64)
|
||||
flags = FFI_IA64_TYPE_SMALL_STRUCT | (16 << 8);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
{
|
||||
size_t size = cif->rtype->size;
|
||||
int hfa_type = hfa_element_type (cif->rtype, 0);
|
||||
|
||||
if (hfa_type != FFI_TYPE_VOID)
|
||||
{
|
||||
size_t nelts = size / hfa_type_size (hfa_type);
|
||||
if (nelts <= 8)
|
||||
flags = hfa_type | (size << 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (size <= 32)
|
||||
flags = FFI_IA64_TYPE_SMALL_STRUCT | (size << 8);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
cif->flags = flags;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern int ffi_call_unix (struct ia64_args *, PTR64, void (*)(void), UINT64);
|
||||
|
||||
void
|
||||
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
struct ia64_args *stack;
|
||||
long i, avn, gpcount, fpcount;
|
||||
ffi_type **p_arg;
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_UNIX);
|
||||
|
||||
/* If we have no spot for a return value, make one. */
|
||||
if (rvalue == NULL && cif->rtype->type != FFI_TYPE_VOID)
|
||||
rvalue = alloca (cif->rtype->size);
|
||||
|
||||
/* Allocate the stack frame. */
|
||||
stack = alloca (cif->bytes);
|
||||
|
||||
gpcount = fpcount = 0;
|
||||
avn = cif->nargs;
|
||||
for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
|
||||
{
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
stack->gp_regs[gpcount++] = *(SINT8 *)avalue[i];
|
||||
break;
|
||||
case FFI_TYPE_UINT8:
|
||||
stack->gp_regs[gpcount++] = *(UINT8 *)avalue[i];
|
||||
break;
|
||||
case FFI_TYPE_SINT16:
|
||||
stack->gp_regs[gpcount++] = *(SINT16 *)avalue[i];
|
||||
break;
|
||||
case FFI_TYPE_UINT16:
|
||||
stack->gp_regs[gpcount++] = *(UINT16 *)avalue[i];
|
||||
break;
|
||||
case FFI_TYPE_SINT32:
|
||||
stack->gp_regs[gpcount++] = *(SINT32 *)avalue[i];
|
||||
break;
|
||||
case FFI_TYPE_UINT32:
|
||||
stack->gp_regs[gpcount++] = *(UINT32 *)avalue[i];
|
||||
break;
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
stack->gp_regs[gpcount++] = *(UINT64 *)avalue[i];
|
||||
break;
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
stack->gp_regs[gpcount++] = (UINT64)(PTR64) *(void **)avalue[i];
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (gpcount < 8 && fpcount < 8)
|
||||
stf_spill (&stack->fp_regs[fpcount++], *(float *)avalue[i]);
|
||||
stack->gp_regs[gpcount++] = *(UINT32 *)avalue[i];
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
if (gpcount < 8 && fpcount < 8)
|
||||
stf_spill (&stack->fp_regs[fpcount++], *(double *)avalue[i]);
|
||||
stack->gp_regs[gpcount++] = *(UINT64 *)avalue[i];
|
||||
break;
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
if (gpcount & 1)
|
||||
gpcount++;
|
||||
if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8)
|
||||
stf_spill (&stack->fp_regs[fpcount++], *(__float80 *)avalue[i]);
|
||||
memcpy (&stack->gp_regs[gpcount], avalue[i], 16);
|
||||
gpcount += 2;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
{
|
||||
size_t size = (*p_arg)->size;
|
||||
size_t align = (*p_arg)->alignment;
|
||||
int hfa_type = hfa_element_type (*p_arg, 0);
|
||||
|
||||
FFI_ASSERT (align <= 16);
|
||||
if (align == 16 && (gpcount & 1))
|
||||
gpcount++;
|
||||
|
||||
if (hfa_type != FFI_TYPE_VOID)
|
||||
{
|
||||
size_t hfa_size = hfa_type_size (hfa_type);
|
||||
size_t offset = 0;
|
||||
size_t gp_offset = gpcount * 8;
|
||||
|
||||
while (fpcount < 8
|
||||
&& offset < size
|
||||
&& gp_offset < 8 * 8)
|
||||
{
|
||||
hfa_type_load (&stack->fp_regs[fpcount], hfa_type,
|
||||
avalue[i] + offset);
|
||||
offset += hfa_size;
|
||||
gp_offset += hfa_size;
|
||||
fpcount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy (&stack->gp_regs[gpcount], avalue[i], size);
|
||||
gpcount += (size + 7) / 8;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
ffi_call_unix (stack, rvalue, fn, cif->flags);
|
||||
}
|
||||
|
||||
/* Closures represent a pair consisting of a function pointer, and
|
||||
some user data. A closure is invoked by reinterpreting the closure
|
||||
as a function pointer, and branching to it. Thus we can make an
|
||||
interpreted function callable as a C function: We turn the
|
||||
interpreter itself, together with a pointer specifying the
|
||||
interpreted procedure, into a closure.
|
||||
|
||||
For IA64, function pointer are already pairs consisting of a code
|
||||
pointer, and a gp pointer. The latter is needed to access global
|
||||
variables. Here we set up such a pair as the first two words of
|
||||
the closure (in the "trampoline" area), but we replace the gp
|
||||
pointer with a pointer to the closure itself. We also add the real
|
||||
gp pointer to the closure. This allows the function entry code to
|
||||
both retrieve the user data, and to restire the correct gp pointer. */
|
||||
|
||||
extern void ffi_closure_unix ();
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
/* The layout of a function descriptor. A C function pointer really
|
||||
points to one of these. */
|
||||
struct ia64_fd
|
||||
{
|
||||
UINT64 code_pointer;
|
||||
UINT64 gp;
|
||||
};
|
||||
|
||||
struct ffi_ia64_trampoline_struct
|
||||
{
|
||||
UINT64 code_pointer; /* Pointer to ffi_closure_unix. */
|
||||
UINT64 fake_gp; /* Pointer to closure, installed as gp. */
|
||||
UINT64 real_gp; /* Real gp value. */
|
||||
};
|
||||
|
||||
struct ffi_ia64_trampoline_struct *tramp;
|
||||
struct ia64_fd *fd;
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_UNIX);
|
||||
|
||||
tramp = (struct ffi_ia64_trampoline_struct *)closure->tramp;
|
||||
fd = (struct ia64_fd *)(void *)ffi_closure_unix;
|
||||
|
||||
tramp->code_pointer = fd->code_pointer;
|
||||
tramp->real_gp = fd->gp;
|
||||
tramp->fake_gp = (UINT64)(PTR64)codeloc;
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
|
||||
UINT64
|
||||
ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack,
|
||||
void *rvalue, void *r8)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
void **avalue;
|
||||
ffi_type **p_arg;
|
||||
long i, avn, gpcount, fpcount;
|
||||
|
||||
cif = closure->cif;
|
||||
avn = cif->nargs;
|
||||
avalue = alloca (avn * sizeof (void *));
|
||||
|
||||
/* If the structure return value is passed in memory get that location
|
||||
from r8 so as to pass the value directly back to the caller. */
|
||||
if (cif->flags == FFI_TYPE_STRUCT)
|
||||
rvalue = r8;
|
||||
|
||||
gpcount = fpcount = 0;
|
||||
for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
|
||||
{
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT8:
|
||||
avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 1);
|
||||
break;
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 2);
|
||||
break;
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 4);
|
||||
break;
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
avalue[i] = &stack->gp_regs[gpcount++];
|
||||
break;
|
||||
case FFI_TYPE_POINTER:
|
||||
avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], sizeof(void*));
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (gpcount < 8 && fpcount < 8)
|
||||
{
|
||||
fpreg *addr = &stack->fp_regs[fpcount++];
|
||||
float result;
|
||||
avalue[i] = addr;
|
||||
ldf_fill (result, addr);
|
||||
*(float *)addr = result;
|
||||
}
|
||||
else
|
||||
avalue[i] = endian_adjust(&stack->gp_regs[gpcount], 4);
|
||||
gpcount++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
if (gpcount < 8 && fpcount < 8)
|
||||
{
|
||||
fpreg *addr = &stack->fp_regs[fpcount++];
|
||||
double result;
|
||||
avalue[i] = addr;
|
||||
ldf_fill (result, addr);
|
||||
*(double *)addr = result;
|
||||
}
|
||||
else
|
||||
avalue[i] = &stack->gp_regs[gpcount];
|
||||
gpcount++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
if (gpcount & 1)
|
||||
gpcount++;
|
||||
if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8)
|
||||
{
|
||||
fpreg *addr = &stack->fp_regs[fpcount++];
|
||||
__float80 result;
|
||||
avalue[i] = addr;
|
||||
ldf_fill (result, addr);
|
||||
*(__float80 *)addr = result;
|
||||
}
|
||||
else
|
||||
avalue[i] = &stack->gp_regs[gpcount];
|
||||
gpcount += 2;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
{
|
||||
size_t size = (*p_arg)->size;
|
||||
size_t align = (*p_arg)->alignment;
|
||||
int hfa_type = hfa_element_type (*p_arg, 0);
|
||||
|
||||
FFI_ASSERT (align <= 16);
|
||||
if (align == 16 && (gpcount & 1))
|
||||
gpcount++;
|
||||
|
||||
if (hfa_type != FFI_TYPE_VOID)
|
||||
{
|
||||
size_t hfa_size = hfa_type_size (hfa_type);
|
||||
size_t offset = 0;
|
||||
size_t gp_offset = gpcount * 8;
|
||||
void *addr = alloca (size);
|
||||
|
||||
avalue[i] = addr;
|
||||
|
||||
while (fpcount < 8
|
||||
&& offset < size
|
||||
&& gp_offset < 8 * 8)
|
||||
{
|
||||
hfa_type_store (hfa_type, addr + offset,
|
||||
&stack->fp_regs[fpcount]);
|
||||
offset += hfa_size;
|
||||
gp_offset += hfa_size;
|
||||
fpcount += 1;
|
||||
}
|
||||
|
||||
if (offset < size)
|
||||
memcpy (addr + offset, (char *)stack->gp_regs + gp_offset,
|
||||
size - offset);
|
||||
}
|
||||
else
|
||||
avalue[i] = &stack->gp_regs[gpcount];
|
||||
|
||||
gpcount += (size + 7) / 8;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
closure->fun (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
return cif->flags;
|
||||
}
|
||||
50
src/ia64/ffitarget.h
Normal file
50
src/ia64/ffitarget.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for IA-64.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long long ffi_arg;
|
||||
typedef signed long long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_UNIX, /* Linux and all Unix variants use the same conventions */
|
||||
FFI_DEFAULT_ABI = FFI_UNIX,
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 24 /* Really the following struct, which */
|
||||
/* can be interpreted as a C function */
|
||||
/* descriptor: */
|
||||
|
||||
#endif
|
||||
|
||||
40
src/ia64/ia64_flags.h
Normal file
40
src/ia64/ia64_flags.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ia64_flags.h - Copyright (c) 2000 Hewlett Packard Company
|
||||
|
||||
IA64/unix Foreign Function Interface
|
||||
|
||||
Original author: Hans Boehm, HP Labs
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
/* "Type" codes used between assembly and C. When used as a part of
|
||||
a cfi->flags value, the low byte will be these extra type codes,
|
||||
and bits 8-31 will be the actual size of the type. */
|
||||
|
||||
/* Small structures containing N words in integer registers. */
|
||||
#define FFI_IA64_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 1)
|
||||
|
||||
/* Homogeneous Floating Point Aggregates (HFAs) which are returned
|
||||
in FP registers. */
|
||||
#define FFI_IA64_TYPE_HFA_FLOAT (FFI_TYPE_LAST + 2)
|
||||
#define FFI_IA64_TYPE_HFA_DOUBLE (FFI_TYPE_LAST + 3)
|
||||
#define FFI_IA64_TYPE_HFA_LDOUBLE (FFI_TYPE_LAST + 4)
|
||||
560
src/ia64/unix.S
Normal file
560
src/ia64/unix.S
Normal file
@@ -0,0 +1,560 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
unix.S - Copyright (c) 1998, 2008 Red Hat, Inc.
|
||||
Copyright (c) 2000 Hewlett Packard Company
|
||||
|
||||
IA64/unix Foreign Function Interface
|
||||
|
||||
Primary author: Hans Boehm, HP Labs
|
||||
|
||||
Loosely modeled on Cygnus code for other platforms.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#include "ia64_flags.h"
|
||||
|
||||
.pred.safe_across_calls p1-p5,p16-p63
|
||||
.text
|
||||
|
||||
/* int ffi_call_unix (struct ia64_args *stack, PTR64 rvalue,
|
||||
void (*fn)(void), int flags);
|
||||
*/
|
||||
|
||||
.align 16
|
||||
.global ffi_call_unix
|
||||
.proc ffi_call_unix
|
||||
ffi_call_unix:
|
||||
.prologue
|
||||
/* Bit o trickiness. We actually share a stack frame with ffi_call.
|
||||
Rely on the fact that ffi_call uses a vframe and don't bother
|
||||
tracking one here at all. */
|
||||
.fframe 0
|
||||
.save ar.pfs, r36 // loc0
|
||||
alloc loc0 = ar.pfs, 4, 3, 8, 0
|
||||
.save rp, loc1
|
||||
mov loc1 = b0
|
||||
.body
|
||||
add r16 = 16, in0
|
||||
mov loc2 = gp
|
||||
mov r8 = in1
|
||||
;;
|
||||
|
||||
/* Load up all of the argument registers. */
|
||||
ldf.fill f8 = [in0], 32
|
||||
ldf.fill f9 = [r16], 32
|
||||
;;
|
||||
ldf.fill f10 = [in0], 32
|
||||
ldf.fill f11 = [r16], 32
|
||||
;;
|
||||
ldf.fill f12 = [in0], 32
|
||||
ldf.fill f13 = [r16], 32
|
||||
;;
|
||||
ldf.fill f14 = [in0], 32
|
||||
ldf.fill f15 = [r16], 24
|
||||
;;
|
||||
ld8 out0 = [in0], 16
|
||||
ld8 out1 = [r16], 16
|
||||
;;
|
||||
ld8 out2 = [in0], 16
|
||||
ld8 out3 = [r16], 16
|
||||
;;
|
||||
ld8 out4 = [in0], 16
|
||||
ld8 out5 = [r16], 16
|
||||
;;
|
||||
ld8 out6 = [in0]
|
||||
ld8 out7 = [r16]
|
||||
;;
|
||||
|
||||
/* Deallocate the register save area from the stack frame. */
|
||||
mov sp = in0
|
||||
|
||||
/* Call the target function. */
|
||||
ld8 r16 = [in2], 8
|
||||
;;
|
||||
ld8 gp = [in2]
|
||||
mov b6 = r16
|
||||
br.call.sptk.many b0 = b6
|
||||
;;
|
||||
|
||||
/* Dispatch to handle return value. */
|
||||
mov gp = loc2
|
||||
zxt1 r16 = in3
|
||||
;;
|
||||
mov ar.pfs = loc0
|
||||
addl r18 = @ltoffx(.Lst_table), gp
|
||||
;;
|
||||
ld8.mov r18 = [r18], .Lst_table
|
||||
mov b0 = loc1
|
||||
;;
|
||||
shladd r18 = r16, 3, r18
|
||||
;;
|
||||
ld8 r17 = [r18]
|
||||
shr in3 = in3, 8
|
||||
;;
|
||||
add r17 = r17, r18
|
||||
;;
|
||||
mov b6 = r17
|
||||
br b6
|
||||
;;
|
||||
|
||||
.Lst_void:
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_uint8:
|
||||
zxt1 r8 = r8
|
||||
;;
|
||||
st8 [in1] = r8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_sint8:
|
||||
sxt1 r8 = r8
|
||||
;;
|
||||
st8 [in1] = r8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_uint16:
|
||||
zxt2 r8 = r8
|
||||
;;
|
||||
st8 [in1] = r8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_sint16:
|
||||
sxt2 r8 = r8
|
||||
;;
|
||||
st8 [in1] = r8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_uint32:
|
||||
zxt4 r8 = r8
|
||||
;;
|
||||
st8 [in1] = r8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_sint32:
|
||||
sxt4 r8 = r8
|
||||
;;
|
||||
st8 [in1] = r8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_int64:
|
||||
st8 [in1] = r8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_float:
|
||||
stfs [in1] = f8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_double:
|
||||
stfd [in1] = f8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_ldouble:
|
||||
stfe [in1] = f8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.Lst_small_struct:
|
||||
add sp = -16, sp
|
||||
cmp.lt p6, p0 = 8, in3
|
||||
cmp.lt p7, p0 = 16, in3
|
||||
cmp.lt p8, p0 = 24, in3
|
||||
;;
|
||||
add r16 = 8, sp
|
||||
add r17 = 16, sp
|
||||
add r18 = 24, sp
|
||||
;;
|
||||
st8 [sp] = r8
|
||||
(p6) st8 [r16] = r9
|
||||
mov out0 = in1
|
||||
(p7) st8 [r17] = r10
|
||||
(p8) st8 [r18] = r11
|
||||
mov out1 = sp
|
||||
mov out2 = in3
|
||||
br.call.sptk.many b0 = memcpy#
|
||||
;;
|
||||
mov ar.pfs = loc0
|
||||
mov b0 = loc1
|
||||
mov gp = loc2
|
||||
br.ret.sptk.many b0
|
||||
|
||||
.Lst_hfa_float:
|
||||
add r16 = 4, in1
|
||||
cmp.lt p6, p0 = 4, in3
|
||||
;;
|
||||
stfs [in1] = f8, 8
|
||||
(p6) stfs [r16] = f9, 8
|
||||
cmp.lt p7, p0 = 8, in3
|
||||
cmp.lt p8, p0 = 12, in3
|
||||
;;
|
||||
(p7) stfs [in1] = f10, 8
|
||||
(p8) stfs [r16] = f11, 8
|
||||
cmp.lt p9, p0 = 16, in3
|
||||
cmp.lt p10, p0 = 20, in3
|
||||
;;
|
||||
(p9) stfs [in1] = f12, 8
|
||||
(p10) stfs [r16] = f13, 8
|
||||
cmp.lt p6, p0 = 24, in3
|
||||
cmp.lt p7, p0 = 28, in3
|
||||
;;
|
||||
(p6) stfs [in1] = f14
|
||||
(p7) stfs [r16] = f15
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.Lst_hfa_double:
|
||||
add r16 = 8, in1
|
||||
cmp.lt p6, p0 = 8, in3
|
||||
;;
|
||||
stfd [in1] = f8, 16
|
||||
(p6) stfd [r16] = f9, 16
|
||||
cmp.lt p7, p0 = 16, in3
|
||||
cmp.lt p8, p0 = 24, in3
|
||||
;;
|
||||
(p7) stfd [in1] = f10, 16
|
||||
(p8) stfd [r16] = f11, 16
|
||||
cmp.lt p9, p0 = 32, in3
|
||||
cmp.lt p10, p0 = 40, in3
|
||||
;;
|
||||
(p9) stfd [in1] = f12, 16
|
||||
(p10) stfd [r16] = f13, 16
|
||||
cmp.lt p6, p0 = 48, in3
|
||||
cmp.lt p7, p0 = 56, in3
|
||||
;;
|
||||
(p6) stfd [in1] = f14
|
||||
(p7) stfd [r16] = f15
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.Lst_hfa_ldouble:
|
||||
add r16 = 16, in1
|
||||
cmp.lt p6, p0 = 16, in3
|
||||
;;
|
||||
stfe [in1] = f8, 32
|
||||
(p6) stfe [r16] = f9, 32
|
||||
cmp.lt p7, p0 = 32, in3
|
||||
cmp.lt p8, p0 = 48, in3
|
||||
;;
|
||||
(p7) stfe [in1] = f10, 32
|
||||
(p8) stfe [r16] = f11, 32
|
||||
cmp.lt p9, p0 = 64, in3
|
||||
cmp.lt p10, p0 = 80, in3
|
||||
;;
|
||||
(p9) stfe [in1] = f12, 32
|
||||
(p10) stfe [r16] = f13, 32
|
||||
cmp.lt p6, p0 = 96, in3
|
||||
cmp.lt p7, p0 = 112, in3
|
||||
;;
|
||||
(p6) stfe [in1] = f14
|
||||
(p7) stfe [r16] = f15
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.endp ffi_call_unix
|
||||
|
||||
.align 16
|
||||
.global ffi_closure_unix
|
||||
.proc ffi_closure_unix
|
||||
|
||||
#define FRAME_SIZE (8*16 + 8*8 + 8*16)
|
||||
|
||||
ffi_closure_unix:
|
||||
.prologue
|
||||
.save ar.pfs, r40 // loc0
|
||||
alloc loc0 = ar.pfs, 8, 4, 4, 0
|
||||
.fframe FRAME_SIZE
|
||||
add r12 = -FRAME_SIZE, r12
|
||||
.save rp, loc1
|
||||
mov loc1 = b0
|
||||
.save ar.unat, loc2
|
||||
mov loc2 = ar.unat
|
||||
.body
|
||||
|
||||
/* Retrieve closure pointer and real gp. */
|
||||
#ifdef _ILP32
|
||||
addp4 out0 = 0, gp
|
||||
addp4 gp = 16, gp
|
||||
#else
|
||||
mov out0 = gp
|
||||
add gp = 16, gp
|
||||
#endif
|
||||
;;
|
||||
ld8 gp = [gp]
|
||||
|
||||
/* Spill all of the possible argument registers. */
|
||||
add r16 = 16 + 8*16, sp
|
||||
add r17 = 16 + 8*16 + 16, sp
|
||||
;;
|
||||
stf.spill [r16] = f8, 32
|
||||
stf.spill [r17] = f9, 32
|
||||
mov loc3 = gp
|
||||
;;
|
||||
stf.spill [r16] = f10, 32
|
||||
stf.spill [r17] = f11, 32
|
||||
;;
|
||||
stf.spill [r16] = f12, 32
|
||||
stf.spill [r17] = f13, 32
|
||||
;;
|
||||
stf.spill [r16] = f14, 32
|
||||
stf.spill [r17] = f15, 24
|
||||
;;
|
||||
.mem.offset 0, 0
|
||||
st8.spill [r16] = in0, 16
|
||||
.mem.offset 8, 0
|
||||
st8.spill [r17] = in1, 16
|
||||
add out1 = 16 + 8*16, sp
|
||||
;;
|
||||
.mem.offset 0, 0
|
||||
st8.spill [r16] = in2, 16
|
||||
.mem.offset 8, 0
|
||||
st8.spill [r17] = in3, 16
|
||||
add out2 = 16, sp
|
||||
;;
|
||||
.mem.offset 0, 0
|
||||
st8.spill [r16] = in4, 16
|
||||
.mem.offset 8, 0
|
||||
st8.spill [r17] = in5, 16
|
||||
mov out3 = r8
|
||||
;;
|
||||
.mem.offset 0, 0
|
||||
st8.spill [r16] = in6
|
||||
.mem.offset 8, 0
|
||||
st8.spill [r17] = in7
|
||||
|
||||
/* Invoke ffi_closure_unix_inner for the hard work. */
|
||||
br.call.sptk.many b0 = ffi_closure_unix_inner
|
||||
;;
|
||||
|
||||
/* Dispatch to handle return value. */
|
||||
mov gp = loc3
|
||||
zxt1 r16 = r8
|
||||
;;
|
||||
addl r18 = @ltoffx(.Lld_table), gp
|
||||
mov ar.pfs = loc0
|
||||
;;
|
||||
ld8.mov r18 = [r18], .Lld_table
|
||||
mov b0 = loc1
|
||||
;;
|
||||
shladd r18 = r16, 3, r18
|
||||
mov ar.unat = loc2
|
||||
;;
|
||||
ld8 r17 = [r18]
|
||||
shr r8 = r8, 8
|
||||
;;
|
||||
add r17 = r17, r18
|
||||
add r16 = 16, sp
|
||||
;;
|
||||
mov b6 = r17
|
||||
br b6
|
||||
;;
|
||||
.label_state 1
|
||||
|
||||
.Lld_void:
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lld_int:
|
||||
.body
|
||||
.copy_state 1
|
||||
ld8 r8 = [r16]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lld_float:
|
||||
.body
|
||||
.copy_state 1
|
||||
ldfs f8 = [r16]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lld_double:
|
||||
.body
|
||||
.copy_state 1
|
||||
ldfd f8 = [r16]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lld_ldouble:
|
||||
.body
|
||||
.copy_state 1
|
||||
ldfe f8 = [r16]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.Lld_small_struct:
|
||||
.body
|
||||
.copy_state 1
|
||||
add r17 = 8, r16
|
||||
cmp.lt p6, p0 = 8, r8
|
||||
cmp.lt p7, p0 = 16, r8
|
||||
cmp.lt p8, p0 = 24, r8
|
||||
;;
|
||||
ld8 r8 = [r16], 16
|
||||
(p6) ld8 r9 = [r17], 16
|
||||
;;
|
||||
(p7) ld8 r10 = [r16]
|
||||
(p8) ld8 r11 = [r17]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.Lld_hfa_float:
|
||||
.body
|
||||
.copy_state 1
|
||||
add r17 = 4, r16
|
||||
cmp.lt p6, p0 = 4, r8
|
||||
;;
|
||||
ldfs f8 = [r16], 8
|
||||
(p6) ldfs f9 = [r17], 8
|
||||
cmp.lt p7, p0 = 8, r8
|
||||
cmp.lt p8, p0 = 12, r8
|
||||
;;
|
||||
(p7) ldfs f10 = [r16], 8
|
||||
(p8) ldfs f11 = [r17], 8
|
||||
cmp.lt p9, p0 = 16, r8
|
||||
cmp.lt p10, p0 = 20, r8
|
||||
;;
|
||||
(p9) ldfs f12 = [r16], 8
|
||||
(p10) ldfs f13 = [r17], 8
|
||||
cmp.lt p6, p0 = 24, r8
|
||||
cmp.lt p7, p0 = 28, r8
|
||||
;;
|
||||
(p6) ldfs f14 = [r16]
|
||||
(p7) ldfs f15 = [r17]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.Lld_hfa_double:
|
||||
.body
|
||||
.copy_state 1
|
||||
add r17 = 8, r16
|
||||
cmp.lt p6, p0 = 8, r8
|
||||
;;
|
||||
ldfd f8 = [r16], 16
|
||||
(p6) ldfd f9 = [r17], 16
|
||||
cmp.lt p7, p0 = 16, r8
|
||||
cmp.lt p8, p0 = 24, r8
|
||||
;;
|
||||
(p7) ldfd f10 = [r16], 16
|
||||
(p8) ldfd f11 = [r17], 16
|
||||
cmp.lt p9, p0 = 32, r8
|
||||
cmp.lt p10, p0 = 40, r8
|
||||
;;
|
||||
(p9) ldfd f12 = [r16], 16
|
||||
(p10) ldfd f13 = [r17], 16
|
||||
cmp.lt p6, p0 = 48, r8
|
||||
cmp.lt p7, p0 = 56, r8
|
||||
;;
|
||||
(p6) ldfd f14 = [r16]
|
||||
(p7) ldfd f15 = [r17]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.Lld_hfa_ldouble:
|
||||
.body
|
||||
.copy_state 1
|
||||
add r17 = 16, r16
|
||||
cmp.lt p6, p0 = 16, r8
|
||||
;;
|
||||
ldfe f8 = [r16], 32
|
||||
(p6) ldfe f9 = [r17], 32
|
||||
cmp.lt p7, p0 = 32, r8
|
||||
cmp.lt p8, p0 = 48, r8
|
||||
;;
|
||||
(p7) ldfe f10 = [r16], 32
|
||||
(p8) ldfe f11 = [r17], 32
|
||||
cmp.lt p9, p0 = 64, r8
|
||||
cmp.lt p10, p0 = 80, r8
|
||||
;;
|
||||
(p9) ldfe f12 = [r16], 32
|
||||
(p10) ldfe f13 = [r17], 32
|
||||
cmp.lt p6, p0 = 96, r8
|
||||
cmp.lt p7, p0 = 112, r8
|
||||
;;
|
||||
(p6) ldfe f14 = [r16]
|
||||
(p7) ldfe f15 = [r17]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.endp ffi_closure_unix
|
||||
|
||||
.section .rodata
|
||||
.align 8
|
||||
.Lst_table:
|
||||
data8 @pcrel(.Lst_void) // FFI_TYPE_VOID
|
||||
data8 @pcrel(.Lst_sint32) // FFI_TYPE_INT
|
||||
data8 @pcrel(.Lst_float) // FFI_TYPE_FLOAT
|
||||
data8 @pcrel(.Lst_double) // FFI_TYPE_DOUBLE
|
||||
data8 @pcrel(.Lst_ldouble) // FFI_TYPE_LONGDOUBLE
|
||||
data8 @pcrel(.Lst_uint8) // FFI_TYPE_UINT8
|
||||
data8 @pcrel(.Lst_sint8) // FFI_TYPE_SINT8
|
||||
data8 @pcrel(.Lst_uint16) // FFI_TYPE_UINT16
|
||||
data8 @pcrel(.Lst_sint16) // FFI_TYPE_SINT16
|
||||
data8 @pcrel(.Lst_uint32) // FFI_TYPE_UINT32
|
||||
data8 @pcrel(.Lst_sint32) // FFI_TYPE_SINT32
|
||||
data8 @pcrel(.Lst_int64) // FFI_TYPE_UINT64
|
||||
data8 @pcrel(.Lst_int64) // FFI_TYPE_SINT64
|
||||
data8 @pcrel(.Lst_void) // FFI_TYPE_STRUCT
|
||||
data8 @pcrel(.Lst_int64) // FFI_TYPE_POINTER
|
||||
data8 @pcrel(.Lst_small_struct) // FFI_IA64_TYPE_SMALL_STRUCT
|
||||
data8 @pcrel(.Lst_hfa_float) // FFI_IA64_TYPE_HFA_FLOAT
|
||||
data8 @pcrel(.Lst_hfa_double) // FFI_IA64_TYPE_HFA_DOUBLE
|
||||
data8 @pcrel(.Lst_hfa_ldouble) // FFI_IA64_TYPE_HFA_LDOUBLE
|
||||
|
||||
.Lld_table:
|
||||
data8 @pcrel(.Lld_void) // FFI_TYPE_VOID
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_INT
|
||||
data8 @pcrel(.Lld_float) // FFI_TYPE_FLOAT
|
||||
data8 @pcrel(.Lld_double) // FFI_TYPE_DOUBLE
|
||||
data8 @pcrel(.Lld_ldouble) // FFI_TYPE_LONGDOUBLE
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_UINT8
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_SINT8
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_UINT16
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_SINT16
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_UINT32
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_SINT32
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_UINT64
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_SINT64
|
||||
data8 @pcrel(.Lld_void) // FFI_TYPE_STRUCT
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_POINTER
|
||||
data8 @pcrel(.Lld_small_struct) // FFI_IA64_TYPE_SMALL_STRUCT
|
||||
data8 @pcrel(.Lld_hfa_float) // FFI_IA64_TYPE_HFA_FLOAT
|
||||
data8 @pcrel(.Lld_hfa_double) // FFI_IA64_TYPE_HFA_DOUBLE
|
||||
data8 @pcrel(.Lld_hfa_ldouble) // FFI_IA64_TYPE_HFA_LDOUBLE
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
356
src/java_raw_api.c
Normal file
356
src/java_raw_api.c
Normal file
@@ -0,0 +1,356 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
java_raw_api.c - Copyright (c) 1999, 2007, 2008 Red Hat, Inc.
|
||||
|
||||
Cloned from raw_api.c
|
||||
|
||||
Raw_api.c author: Kresten Krab Thorup <krab@gnu.org>
|
||||
Java_raw_api.c author: Hans-J. Boehm <hboehm@hpl.hp.com>
|
||||
|
||||
$Id $
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
/* This defines a Java- and 64-bit specific variant of the raw API. */
|
||||
/* It assumes that "raw" argument blocks look like Java stacks on a */
|
||||
/* 64-bit machine. Arguments that can be stored in a single stack */
|
||||
/* stack slots (longs, doubles) occupy 128 bits, but only the first */
|
||||
/* 64 bits are actually used. */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if !defined(NO_JAVA_RAW_API) && !defined(FFI_NO_RAW_API)
|
||||
|
||||
size_t
|
||||
ffi_java_raw_size (ffi_cif *cif)
|
||||
{
|
||||
size_t result = 0;
|
||||
int i;
|
||||
|
||||
ffi_type **at = cif->arg_types;
|
||||
|
||||
for (i = cif->nargs-1; i >= 0; i--, at++)
|
||||
{
|
||||
switch((*at) -> type) {
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
result += 2 * FFI_SIZEOF_JAVA_RAW;
|
||||
break;
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* No structure parameters in Java. */
|
||||
abort();
|
||||
default:
|
||||
result += FFI_SIZEOF_JAVA_RAW;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args)
|
||||
{
|
||||
unsigned i;
|
||||
ffi_type **tp = cif->arg_types;
|
||||
|
||||
#if WORDS_BIGENDIAN
|
||||
|
||||
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
||||
{
|
||||
switch ((*tp)->type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_SINT8:
|
||||
*args = (void*) ((char*)(raw++) + 3);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT16:
|
||||
*args = (void*) ((char*)(raw++) + 2);
|
||||
break;
|
||||
|
||||
#if FFI_SIZEOF_JAVA_RAW == 8
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
*args = (void *)raw;
|
||||
raw += 2;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
*args = (void*) &(raw++)->ptr;
|
||||
break;
|
||||
|
||||
default:
|
||||
*args = raw;
|
||||
raw +=
|
||||
ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
|
||||
}
|
||||
}
|
||||
|
||||
#else /* WORDS_BIGENDIAN */
|
||||
|
||||
#if !PDP
|
||||
|
||||
/* then assume little endian */
|
||||
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
||||
{
|
||||
#if FFI_SIZEOF_JAVA_RAW == 8
|
||||
switch((*tp)->type) {
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
*args = (void*) raw;
|
||||
raw += 2;
|
||||
break;
|
||||
default:
|
||||
*args = (void*) raw++;
|
||||
}
|
||||
#else /* FFI_SIZEOF_JAVA_RAW != 8 */
|
||||
*args = (void*) raw;
|
||||
raw +=
|
||||
ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
|
||||
#endif /* FFI_SIZEOF_JAVA_RAW == 8 */
|
||||
}
|
||||
|
||||
#else
|
||||
#error "pdp endian not supported"
|
||||
#endif /* ! PDP */
|
||||
|
||||
#endif /* WORDS_BIGENDIAN */
|
||||
}
|
||||
|
||||
void
|
||||
ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw)
|
||||
{
|
||||
unsigned i;
|
||||
ffi_type **tp = cif->arg_types;
|
||||
|
||||
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
||||
{
|
||||
switch ((*tp)->type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
#if WORDS_BIGENDIAN
|
||||
*(UINT32*)(raw++) = *(UINT8*) (*args);
|
||||
#else
|
||||
(raw++)->uint = *(UINT8*) (*args);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT8:
|
||||
#if WORDS_BIGENDIAN
|
||||
*(SINT32*)(raw++) = *(SINT8*) (*args);
|
||||
#else
|
||||
(raw++)->sint = *(SINT8*) (*args);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
#if WORDS_BIGENDIAN
|
||||
*(UINT32*)(raw++) = *(UINT16*) (*args);
|
||||
#else
|
||||
(raw++)->uint = *(UINT16*) (*args);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
#if WORDS_BIGENDIAN
|
||||
*(SINT32*)(raw++) = *(SINT16*) (*args);
|
||||
#else
|
||||
(raw++)->sint = *(SINT16*) (*args);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
#if WORDS_BIGENDIAN
|
||||
*(UINT32*)(raw++) = *(UINT32*) (*args);
|
||||
#else
|
||||
(raw++)->uint = *(UINT32*) (*args);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
#if WORDS_BIGENDIAN
|
||||
*(SINT32*)(raw++) = *(SINT32*) (*args);
|
||||
#else
|
||||
(raw++)->sint = *(SINT32*) (*args);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
(raw++)->flt = *(FLOAT32*) (*args);
|
||||
break;
|
||||
|
||||
#if FFI_SIZEOF_JAVA_RAW == 8
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
raw->uint = *(UINT64*) (*args);
|
||||
raw += 2;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
(raw++)->ptr = **(void***) args;
|
||||
break;
|
||||
|
||||
default:
|
||||
#if FFI_SIZEOF_JAVA_RAW == 8
|
||||
FFI_ASSERT(0); /* Should have covered all cases */
|
||||
#else
|
||||
memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
|
||||
raw +=
|
||||
ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !FFI_NATIVE_RAW_API
|
||||
|
||||
static void
|
||||
ffi_java_rvalue_to_raw (ffi_cif *cif, void *rvalue)
|
||||
{
|
||||
#if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_UINT32:
|
||||
*(UINT64 *)rvalue <<= 32;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_INT:
|
||||
#if FFI_SIZEOF_JAVA_RAW == 4
|
||||
case FFI_TYPE_POINTER:
|
||||
#endif
|
||||
*(SINT64 *)rvalue <<= 32;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
ffi_java_raw_to_rvalue (ffi_cif *cif, void *rvalue)
|
||||
{
|
||||
#if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_UINT32:
|
||||
*(UINT64 *)rvalue >>= 32;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_INT:
|
||||
*(SINT64 *)rvalue >>= 32;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This is a generic definition of ffi_raw_call, to be used if the
|
||||
* native system does not provide a machine-specific implementation.
|
||||
* Having this, allows code to be written for the raw API, without
|
||||
* the need for system-specific code to handle input in that format;
|
||||
* these following couple of functions will handle the translation forth
|
||||
* and back automatically. */
|
||||
|
||||
void ffi_java_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue,
|
||||
ffi_java_raw *raw)
|
||||
{
|
||||
void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
|
||||
ffi_java_raw_to_ptrarray (cif, raw, avalue);
|
||||
ffi_call (cif, fn, rvalue, avalue);
|
||||
ffi_java_rvalue_to_raw (cif, rvalue);
|
||||
}
|
||||
|
||||
#if FFI_CLOSURES /* base system provides closures */
|
||||
|
||||
static void
|
||||
ffi_java_translate_args (ffi_cif *cif, void *rvalue,
|
||||
void **avalue, void *user_data)
|
||||
{
|
||||
ffi_java_raw *raw = (ffi_java_raw*)alloca (ffi_java_raw_size (cif));
|
||||
ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
|
||||
|
||||
ffi_java_ptrarray_to_raw (cif, avalue, raw);
|
||||
(*cl->fun) (cif, rvalue, raw, cl->user_data);
|
||||
ffi_java_raw_to_rvalue (cif, rvalue);
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_java_raw_closure_loc (ffi_java_raw_closure* cl,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
ffi_status status;
|
||||
|
||||
status = ffi_prep_closure_loc ((ffi_closure*) cl,
|
||||
cif,
|
||||
&ffi_java_translate_args,
|
||||
codeloc,
|
||||
codeloc);
|
||||
if (status == FFI_OK)
|
||||
{
|
||||
cl->fun = fun;
|
||||
cl->user_data = user_data;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Again, here is the generic version of ffi_prep_raw_closure, which
|
||||
* will install an intermediate "hub" for translation of arguments from
|
||||
* the pointer-array format, to the raw format */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_java_raw_closure (ffi_java_raw_closure* cl,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
|
||||
void *user_data)
|
||||
{
|
||||
return ffi_prep_java_raw_closure_loc (cl, cif, fun, user_data, cl);
|
||||
}
|
||||
|
||||
#endif /* FFI_CLOSURES */
|
||||
#endif /* !FFI_NATIVE_RAW_API */
|
||||
#endif /* !FFI_NO_RAW_API */
|
||||
130
src/m32r/.svn/entries
Normal file
130
src/m32r/.svn/entries
Normal file
@@ -0,0 +1,130 @@
|
||||
10
|
||||
|
||||
dir
|
||||
152280
|
||||
svn://gcc.gnu.org/svn/gcc/trunk/libffi/src/m32r
|
||||
svn://gcc.gnu.org/svn/gcc
|
||||
|
||||
|
||||
|
||||
2009-06-04T15:43:03.499507Z
|
||||
148172
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
138bc75d-0d04-0410-961f-82ee72b054a4
|
||||
|
||||
ffitarget.h
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-04-24T17:46:15.000000Z
|
||||
1cf60578f42fad0141df7c5c8a43a407
|
||||
2004-10-25T08:55:44.000000Z
|
||||
89527
|
||||
nickc
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1792
|
||||
|
||||
ffi.c
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:01.000000Z
|
||||
1b85561d6e15d52975a28e0729d7d120
|
||||
2009-06-04T15:43:03.499507Z
|
||||
148172
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
5581
|
||||
|
||||
sysv.S
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-04-24T17:46:15.000000Z
|
||||
fde1f5cb81ab7ce114af861c94c368c0
|
||||
2004-10-13T17:20:24.000000Z
|
||||
88993
|
||||
nickc
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
3050
|
||||
|
||||
232
src/m32r/.svn/text-base/ffi.c.svn-base
Normal file
232
src/m32r/.svn/text-base/ffi.c.svn-base
Normal file
@@ -0,0 +1,232 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2004 Renesas Technology
|
||||
Copyright (c) 2008 Red Hat, Inc.
|
||||
|
||||
M32R 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 RENESAS TECHNOLOGY 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* 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)
|
||||
{
|
||||
unsigned int i;
|
||||
int tmp;
|
||||
unsigned int avn;
|
||||
void **p_argv;
|
||||
char *argp;
|
||||
ffi_type **p_arg;
|
||||
|
||||
tmp = 0;
|
||||
argp = stack;
|
||||
|
||||
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT && ecif->cif->rtype->size > 8)
|
||||
{
|
||||
*(void **) argp = ecif->rvalue;
|
||||
argp += 4;
|
||||
}
|
||||
|
||||
avn = ecif->cif->nargs;
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
(i != 0) && (avn != 0);
|
||||
i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
/* Align if necessary. */
|
||||
if (((*p_arg)->alignment - 1) & (unsigned) argp)
|
||||
argp = (char *) ALIGN (argp, (*p_arg)->alignment);
|
||||
|
||||
if (avn != 0)
|
||||
{
|
||||
avn--;
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof (int))
|
||||
{
|
||||
z = sizeof (int);
|
||||
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
z = (*p_arg)->size;
|
||||
if ((*p_arg)->alignment != 1)
|
||||
memcpy (argp, *p_argv, z);
|
||||
else
|
||||
memcpy (argp + 4 - z, *p_argv, z);
|
||||
z = sizeof (int);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
}
|
||||
else if (z == sizeof (int))
|
||||
{
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((*p_arg)->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
if (z > 8)
|
||||
{
|
||||
*(unsigned int *) argp = (unsigned int)(void *)(* p_argv);
|
||||
z = sizeof(void *);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(argp, *p_argv, z);
|
||||
z = 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Double or long long 64bit. */
|
||||
memcpy (argp, *p_argv, z);
|
||||
}
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing. */
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
/* Set the return type flag. */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
if (cif->rtype->size <= 4)
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
|
||||
else if (cif->rtype->size <= 8)
|
||||
cif->flags = FFI_TYPE_DOUBLE;
|
||||
|
||||
else
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags = FFI_TYPE_DOUBLE;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
|
||||
unsigned, unsigned, unsigned *, void (*fn)(void));
|
||||
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(void), 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);
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
int size = cif->rtype->size;
|
||||
int align = cif->rtype->alignment;
|
||||
|
||||
if (size < 4)
|
||||
{
|
||||
if (align == 1)
|
||||
*(unsigned long *)(ecif.rvalue) <<= (4 - size) * 8;
|
||||
}
|
||||
else if (4 < size && size < 8)
|
||||
{
|
||||
if (align == 1)
|
||||
{
|
||||
memcpy (ecif.rvalue, ecif.rvalue + 8-size, size);
|
||||
}
|
||||
else if (align == 2)
|
||||
{
|
||||
if (size & 1)
|
||||
size += 1;
|
||||
|
||||
if (size != 8)
|
||||
memcpy (ecif.rvalue, ecif.rvalue + 8-size, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
48
src/m32r/.svn/text-base/ffitarget.h.svn-base
Normal file
48
src/m32r/.svn/text-base/ffitarget.h.svn-base
Normal file
@@ -0,0 +1,48 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 2004 Renesas Technology.
|
||||
Target configuration macros for M32R.
|
||||
|
||||
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 RENESAS TECHNOLOGY 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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
/* ---- Generic type definitions ----------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi
|
||||
{
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_SYSV,
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
#define FFI_CLOSURES 0
|
||||
#define FFI_TRAMPOLINE_SIZE 24
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
121
src/m32r/.svn/text-base/sysv.S.svn-base
Normal file
121
src/m32r/.svn/text-base/sysv.S.svn-base
Normal file
@@ -0,0 +1,121 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 2004 Renesas Technology
|
||||
|
||||
M32R 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 RENESAS TECHNOLOGY 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#ifdef HAVE_MACHINE_ASM_H
|
||||
#include <machine/asm.h>
|
||||
#else
|
||||
/* XXX these lose for some platforms, I'm sure. */
|
||||
#define CNAME(x) x
|
||||
#define ENTRY(x) .globl CNAME(x)! .type CNAME(x),%function! CNAME(x):
|
||||
#endif
|
||||
|
||||
.text
|
||||
|
||||
/* R0: ffi_prep_args */
|
||||
/* R1: &ecif */
|
||||
/* R2: cif->bytes */
|
||||
/* R3: fig->flags */
|
||||
/* sp+0: ecif.rvalue */
|
||||
/* sp+4: fn */
|
||||
|
||||
/* This assumes we are using gas. */
|
||||
ENTRY(ffi_call_SYSV)
|
||||
/* Save registers. */
|
||||
push fp
|
||||
push lr
|
||||
push r3
|
||||
push r2
|
||||
push r1
|
||||
push r0
|
||||
mv fp, sp
|
||||
|
||||
/* Make room for all of the new args. */
|
||||
sub sp, r2
|
||||
|
||||
/* Place all of the ffi_prep_args in position. */
|
||||
mv lr, r0
|
||||
mv r0, sp
|
||||
/* R1 already set. */
|
||||
|
||||
/* And call. */
|
||||
jl lr
|
||||
|
||||
/* Move first 4 parameters in registers... */
|
||||
ld r0, @(0,sp)
|
||||
ld r1, @(4,sp)
|
||||
ld r2, @(8,sp)
|
||||
ld r3, @(12,sp)
|
||||
|
||||
/* ...and adjust the stack. */
|
||||
ld lr, @(8,fp)
|
||||
cmpi lr, #16
|
||||
bc adjust_stack
|
||||
ldi lr, #16
|
||||
adjust_stack:
|
||||
add sp, lr
|
||||
|
||||
/* Call the function. */
|
||||
ld lr, @(28,fp)
|
||||
jl lr
|
||||
|
||||
/* Remove the space we pushed for the args. */
|
||||
mv sp, fp
|
||||
|
||||
/* Load R2 with the pointer to storage for the return value. */
|
||||
ld r2, @(24,sp)
|
||||
|
||||
/* Load R3 with the return type code. */
|
||||
ld r3, @(12,sp)
|
||||
|
||||
/* If the return value pointer is NULL, assume no return value. */
|
||||
beqz r2, epilogue
|
||||
|
||||
/* Return INT. */
|
||||
ldi r4, #FFI_TYPE_INT
|
||||
bne r3, r4, return_double
|
||||
st r0, @r2
|
||||
bra epilogue
|
||||
|
||||
return_double:
|
||||
/* Return DOUBLE or LONGDOUBLE. */
|
||||
ldi r4, #FFI_TYPE_DOUBLE
|
||||
bne r3, r4, epilogue
|
||||
st r0, @r2
|
||||
st r1, @(4,r2)
|
||||
|
||||
epilogue:
|
||||
pop r0
|
||||
pop r1
|
||||
pop r2
|
||||
pop r3
|
||||
pop lr
|
||||
pop fp
|
||||
jmp lr
|
||||
|
||||
.ffi_call_SYSV_end:
|
||||
.size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
|
||||
232
src/m32r/ffi.c
Normal file
232
src/m32r/ffi.c
Normal file
@@ -0,0 +1,232 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2004 Renesas Technology
|
||||
Copyright (c) 2008 Red Hat, Inc.
|
||||
|
||||
M32R 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 RENESAS TECHNOLOGY 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* 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)
|
||||
{
|
||||
unsigned int i;
|
||||
int tmp;
|
||||
unsigned int avn;
|
||||
void **p_argv;
|
||||
char *argp;
|
||||
ffi_type **p_arg;
|
||||
|
||||
tmp = 0;
|
||||
argp = stack;
|
||||
|
||||
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT && ecif->cif->rtype->size > 8)
|
||||
{
|
||||
*(void **) argp = ecif->rvalue;
|
||||
argp += 4;
|
||||
}
|
||||
|
||||
avn = ecif->cif->nargs;
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
(i != 0) && (avn != 0);
|
||||
i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
/* Align if necessary. */
|
||||
if (((*p_arg)->alignment - 1) & (unsigned) argp)
|
||||
argp = (char *) ALIGN (argp, (*p_arg)->alignment);
|
||||
|
||||
if (avn != 0)
|
||||
{
|
||||
avn--;
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof (int))
|
||||
{
|
||||
z = sizeof (int);
|
||||
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
z = (*p_arg)->size;
|
||||
if ((*p_arg)->alignment != 1)
|
||||
memcpy (argp, *p_argv, z);
|
||||
else
|
||||
memcpy (argp + 4 - z, *p_argv, z);
|
||||
z = sizeof (int);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
}
|
||||
else if (z == sizeof (int))
|
||||
{
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((*p_arg)->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
if (z > 8)
|
||||
{
|
||||
*(unsigned int *) argp = (unsigned int)(void *)(* p_argv);
|
||||
z = sizeof(void *);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(argp, *p_argv, z);
|
||||
z = 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Double or long long 64bit. */
|
||||
memcpy (argp, *p_argv, z);
|
||||
}
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing. */
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
/* Set the return type flag. */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
if (cif->rtype->size <= 4)
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
|
||||
else if (cif->rtype->size <= 8)
|
||||
cif->flags = FFI_TYPE_DOUBLE;
|
||||
|
||||
else
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags = FFI_TYPE_DOUBLE;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
|
||||
unsigned, unsigned, unsigned *, void (*fn)(void));
|
||||
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(void), 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);
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
int size = cif->rtype->size;
|
||||
int align = cif->rtype->alignment;
|
||||
|
||||
if (size < 4)
|
||||
{
|
||||
if (align == 1)
|
||||
*(unsigned long *)(ecif.rvalue) <<= (4 - size) * 8;
|
||||
}
|
||||
else if (4 < size && size < 8)
|
||||
{
|
||||
if (align == 1)
|
||||
{
|
||||
memcpy (ecif.rvalue, ecif.rvalue + 8-size, size);
|
||||
}
|
||||
else if (align == 2)
|
||||
{
|
||||
if (size & 1)
|
||||
size += 1;
|
||||
|
||||
if (size != 8)
|
||||
memcpy (ecif.rvalue, ecif.rvalue + 8-size, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
48
src/m32r/ffitarget.h
Normal file
48
src/m32r/ffitarget.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 2004 Renesas Technology.
|
||||
Target configuration macros for M32R.
|
||||
|
||||
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 RENESAS TECHNOLOGY 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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
/* ---- Generic type definitions ----------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi
|
||||
{
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_SYSV,
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
#define FFI_CLOSURES 0
|
||||
#define FFI_TRAMPOLINE_SIZE 24
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
121
src/m32r/sysv.S
Normal file
121
src/m32r/sysv.S
Normal file
@@ -0,0 +1,121 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 2004 Renesas Technology
|
||||
|
||||
M32R 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 RENESAS TECHNOLOGY 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#ifdef HAVE_MACHINE_ASM_H
|
||||
#include <machine/asm.h>
|
||||
#else
|
||||
/* XXX these lose for some platforms, I'm sure. */
|
||||
#define CNAME(x) x
|
||||
#define ENTRY(x) .globl CNAME(x)! .type CNAME(x),%function! CNAME(x):
|
||||
#endif
|
||||
|
||||
.text
|
||||
|
||||
/* R0: ffi_prep_args */
|
||||
/* R1: &ecif */
|
||||
/* R2: cif->bytes */
|
||||
/* R3: fig->flags */
|
||||
/* sp+0: ecif.rvalue */
|
||||
/* sp+4: fn */
|
||||
|
||||
/* This assumes we are using gas. */
|
||||
ENTRY(ffi_call_SYSV)
|
||||
/* Save registers. */
|
||||
push fp
|
||||
push lr
|
||||
push r3
|
||||
push r2
|
||||
push r1
|
||||
push r0
|
||||
mv fp, sp
|
||||
|
||||
/* Make room for all of the new args. */
|
||||
sub sp, r2
|
||||
|
||||
/* Place all of the ffi_prep_args in position. */
|
||||
mv lr, r0
|
||||
mv r0, sp
|
||||
/* R1 already set. */
|
||||
|
||||
/* And call. */
|
||||
jl lr
|
||||
|
||||
/* Move first 4 parameters in registers... */
|
||||
ld r0, @(0,sp)
|
||||
ld r1, @(4,sp)
|
||||
ld r2, @(8,sp)
|
||||
ld r3, @(12,sp)
|
||||
|
||||
/* ...and adjust the stack. */
|
||||
ld lr, @(8,fp)
|
||||
cmpi lr, #16
|
||||
bc adjust_stack
|
||||
ldi lr, #16
|
||||
adjust_stack:
|
||||
add sp, lr
|
||||
|
||||
/* Call the function. */
|
||||
ld lr, @(28,fp)
|
||||
jl lr
|
||||
|
||||
/* Remove the space we pushed for the args. */
|
||||
mv sp, fp
|
||||
|
||||
/* Load R2 with the pointer to storage for the return value. */
|
||||
ld r2, @(24,sp)
|
||||
|
||||
/* Load R3 with the return type code. */
|
||||
ld r3, @(12,sp)
|
||||
|
||||
/* If the return value pointer is NULL, assume no return value. */
|
||||
beqz r2, epilogue
|
||||
|
||||
/* Return INT. */
|
||||
ldi r4, #FFI_TYPE_INT
|
||||
bne r3, r4, return_double
|
||||
st r0, @r2
|
||||
bra epilogue
|
||||
|
||||
return_double:
|
||||
/* Return DOUBLE or LONGDOUBLE. */
|
||||
ldi r4, #FFI_TYPE_DOUBLE
|
||||
bne r3, r4, epilogue
|
||||
st r0, @r2
|
||||
st r1, @(4,r2)
|
||||
|
||||
epilogue:
|
||||
pop r0
|
||||
pop r1
|
||||
pop r2
|
||||
pop r3
|
||||
pop lr
|
||||
pop fp
|
||||
jmp lr
|
||||
|
||||
.ffi_call_SYSV_end:
|
||||
.size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
|
||||
130
src/m68k/.svn/entries
Normal file
130
src/m68k/.svn/entries
Normal file
@@ -0,0 +1,130 @@
|
||||
10
|
||||
|
||||
dir
|
||||
152280
|
||||
svn://gcc.gnu.org/svn/gcc/trunk/libffi/src/m68k
|
||||
svn://gcc.gnu.org/svn/gcc
|
||||
|
||||
|
||||
|
||||
2009-06-04T15:43:03.499507Z
|
||||
148172
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
138bc75d-0d04-0410-961f-82ee72b054a4
|
||||
|
||||
ffitarget.h
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:01.000000Z
|
||||
7466dbaa771ba740ab8801f3389643e9
|
||||
2009-06-04T15:11:12.475454Z
|
||||
148171
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1803
|
||||
|
||||
ffi.c
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-04-24T17:46:15.000000Z
|
||||
8d851db95dfd81e850d6032b8e2b9060
|
||||
2007-05-10T21:29:04.628473Z
|
||||
124601
|
||||
zippel
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
5691
|
||||
|
||||
sysv.S
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:01.000000Z
|
||||
9de0630e99a0b634afe5519c60c2be86
|
||||
2009-06-04T15:43:03.499507Z
|
||||
148172
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
4800
|
||||
|
||||
278
src/m68k/.svn/text-base/ffi.c.svn-base
Normal file
278
src/m68k/.svn/text-base/ffi.c.svn-base
Normal file
@@ -0,0 +1,278 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c
|
||||
|
||||
m68k Foreign Function Interface
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <asm/cachectl.h>
|
||||
|
||||
void ffi_call_SYSV (extended_cif *,
|
||||
unsigned, unsigned,
|
||||
void *, void (*fn) ());
|
||||
void *ffi_prep_args (void *stack, extended_cif *ecif);
|
||||
void ffi_closure_SYSV (ffi_closure *);
|
||||
void ffi_closure_struct_SYSV (ffi_closure *);
|
||||
unsigned int ffi_closure_SYSV_inner (ffi_closure *closure,
|
||||
void *resp, void *args);
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack space has
|
||||
been allocated for the function's arguments. */
|
||||
|
||||
void *
|
||||
ffi_prep_args (void *stack, extended_cif *ecif)
|
||||
{
|
||||
unsigned int i;
|
||||
void **p_argv;
|
||||
char *argp;
|
||||
ffi_type **p_arg;
|
||||
void *struct_value_ptr;
|
||||
|
||||
argp = stack;
|
||||
|
||||
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
|
||||
&& !ecif->cif->flags)
|
||||
struct_value_ptr = ecif->rvalue;
|
||||
else
|
||||
struct_value_ptr = NULL;
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
i != 0;
|
||||
i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof (int))
|
||||
{
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
memcpy (argp + sizeof (int) - z, *p_argv, z);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
}
|
||||
z = sizeof (int);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (argp, *p_argv, z);
|
||||
|
||||
/* Align if necessary. */
|
||||
if ((sizeof(int) - 1) & z)
|
||||
z = ALIGN(z, sizeof(int));
|
||||
}
|
||||
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
|
||||
return struct_value_ptr;
|
||||
}
|
||||
|
||||
#define CIF_FLAGS_INT 1
|
||||
#define CIF_FLAGS_DINT 2
|
||||
#define CIF_FLAGS_FLOAT 4
|
||||
#define CIF_FLAGS_DOUBLE 8
|
||||
#define CIF_FLAGS_LDOUBLE 16
|
||||
#define CIF_FLAGS_POINTER 32
|
||||
#define CIF_FLAGS_STRUCT1 64
|
||||
#define CIF_FLAGS_STRUCT2 128
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep (ffi_cif *cif)
|
||||
{
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
cif->flags = 0;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
switch (cif->rtype->size)
|
||||
{
|
||||
case 1:
|
||||
cif->flags = CIF_FLAGS_STRUCT1;
|
||||
break;
|
||||
case 2:
|
||||
cif->flags = CIF_FLAGS_STRUCT2;
|
||||
break;
|
||||
case 4:
|
||||
cif->flags = CIF_FLAGS_INT;
|
||||
break;
|
||||
case 8:
|
||||
cif->flags = CIF_FLAGS_DINT;
|
||||
break;
|
||||
default:
|
||||
cif->flags = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
cif->flags = CIF_FLAGS_FLOAT;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags = CIF_FLAGS_DOUBLE;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
cif->flags = CIF_FLAGS_LDOUBLE;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
cif->flags = CIF_FLAGS_POINTER;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
cif->flags = CIF_FLAGS_DINT;
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags = CIF_FLAGS_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
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
|
||||
&& cif->rtype->size > 8)
|
||||
ecif.rvalue = alloca (cif->rtype->size);
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
ffi_call_SYSV (&ecif, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ffi_prep_incoming_args_SYSV (char *stack, void **avalue, ffi_cif *cif)
|
||||
{
|
||||
unsigned int i;
|
||||
void **p_argv;
|
||||
char *argp;
|
||||
ffi_type **p_arg;
|
||||
|
||||
argp = stack;
|
||||
p_argv = avalue;
|
||||
|
||||
for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
z = (*p_arg)->size;
|
||||
if (z <= 4)
|
||||
{
|
||||
*p_argv = (void *) (argp + 4 - z);
|
||||
|
||||
z = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
*p_argv = (void *) argp;
|
||||
|
||||
/* Align if necessary */
|
||||
if ((sizeof(int) - 1) & z)
|
||||
z = ALIGN(z, sizeof(int));
|
||||
}
|
||||
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int
|
||||
ffi_closure_SYSV_inner (ffi_closure *closure, void *resp, void *args)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
void **arg_area;
|
||||
|
||||
cif = closure->cif;
|
||||
arg_area = (void**) alloca (cif->nargs * sizeof (void *));
|
||||
|
||||
ffi_prep_incoming_args_SYSV(args, arg_area, cif);
|
||||
|
||||
(closure->fun) (cif, resp, arg_area, closure->user_data);
|
||||
|
||||
return cif->flags;
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
FFI_ASSERT (cif->abi == FFI_SYSV);
|
||||
|
||||
*(unsigned short *)closure->tramp = 0x207c;
|
||||
*(void **)(closure->tramp + 2) = codeloc;
|
||||
*(unsigned short *)(closure->tramp + 6) = 0x4ef9;
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT
|
||||
&& !cif->flags)
|
||||
*(void **)(closure->tramp + 8) = ffi_closure_struct_SYSV;
|
||||
else
|
||||
*(void **)(closure->tramp + 8) = ffi_closure_SYSV;
|
||||
|
||||
syscall(SYS_cacheflush, codeloc, FLUSH_SCOPE_LINE,
|
||||
FLUSH_CACHE_BOTH, FFI_TRAMPOLINE_SIZE);
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
49
src/m68k/.svn/text-base/ffitarget.h.svn-base
Normal file
49
src/m68k/.svn/text-base/ffitarget.h.svn-base
Normal file
@@ -0,0 +1,49 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for Motorola 68K.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_SYSV,
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 16
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
|
||||
234
src/m68k/.svn/text-base/sysv.S.svn-base
Normal file
234
src/m68k/.svn/text-base/sysv.S.svn-base
Normal file
@@ -0,0 +1,234 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 1998 Andreas Schwab
|
||||
Copyright (c) 2008 Red Hat, Inc.
|
||||
|
||||
m68k 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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
#ifdef HAVE_AS_CFI_PSEUDO_OP
|
||||
#define CFI_STARTPROC() .cfi_startproc
|
||||
#define CFI_OFFSET(reg,off) .cfi_offset reg,off
|
||||
#define CFI_DEF_CFA(reg,off) .cfi_def_cfa reg,off
|
||||
#define CFI_ENDPROC() .cfi_endproc
|
||||
#else
|
||||
#define CFI_STARTPROC()
|
||||
#define CFI_OFFSET(reg,off)
|
||||
#define CFI_DEF_CFA(reg,off)
|
||||
#define CFI_ENDPROC()
|
||||
#endif
|
||||
|
||||
.text
|
||||
|
||||
.globl ffi_call_SYSV
|
||||
.type ffi_call_SYSV,@function
|
||||
.align 4
|
||||
|
||||
ffi_call_SYSV:
|
||||
CFI_STARTPROC()
|
||||
link %fp,#0
|
||||
CFI_OFFSET(14,-8)
|
||||
CFI_DEF_CFA(14,8)
|
||||
move.l %d2,-(%sp)
|
||||
CFI_OFFSET(2,-12)
|
||||
|
||||
| Make room for all of the new args.
|
||||
sub.l 12(%fp),%sp
|
||||
|
||||
| Call ffi_prep_args
|
||||
move.l 8(%fp),-(%sp)
|
||||
pea 4(%sp)
|
||||
#if !defined __PIC__
|
||||
jsr ffi_prep_args
|
||||
#else
|
||||
bsr.l ffi_prep_args@PLTPC
|
||||
#endif
|
||||
addq.l #8,%sp
|
||||
|
||||
| Pass pointer to struct value, if any
|
||||
move.l %a0,%a1
|
||||
|
||||
| Call the function
|
||||
move.l 24(%fp),%a0
|
||||
jsr (%a0)
|
||||
|
||||
| Remove the space we pushed for the args
|
||||
add.l 12(%fp),%sp
|
||||
|
||||
| Load the pointer to storage for the return value
|
||||
move.l 20(%fp),%a1
|
||||
|
||||
| Load the return type code
|
||||
move.l 16(%fp),%d2
|
||||
|
||||
| If the return value pointer is NULL, assume no return value.
|
||||
tst.l %a1
|
||||
jbeq noretval
|
||||
|
||||
btst #0,%d2
|
||||
jbeq retlongint
|
||||
move.l %d0,(%a1)
|
||||
jbra epilogue
|
||||
|
||||
retlongint:
|
||||
btst #1,%d2
|
||||
jbeq retfloat
|
||||
move.l %d0,(%a1)
|
||||
move.l %d1,4(%a1)
|
||||
jbra epilogue
|
||||
|
||||
retfloat:
|
||||
btst #2,%d2
|
||||
jbeq retdouble
|
||||
fmove.s %fp0,(%a1)
|
||||
jbra epilogue
|
||||
|
||||
retdouble:
|
||||
btst #3,%d2
|
||||
jbeq retlongdouble
|
||||
fmove.d %fp0,(%a1)
|
||||
jbra epilogue
|
||||
|
||||
retlongdouble:
|
||||
btst #4,%d2
|
||||
jbeq retpointer
|
||||
fmove.x %fp0,(%a1)
|
||||
jbra epilogue
|
||||
|
||||
retpointer:
|
||||
btst #5,%d2
|
||||
jbeq retstruct1
|
||||
move.l %a0,(%a1)
|
||||
jbra epilogue
|
||||
|
||||
retstruct1:
|
||||
btst #6,%d2
|
||||
jbeq retstruct2
|
||||
move.b %d0,(%a1)
|
||||
jbra epilogue
|
||||
|
||||
retstruct2:
|
||||
btst #7,%d2
|
||||
jbeq noretval
|
||||
move.w %d0,(%a1)
|
||||
|
||||
noretval:
|
||||
epilogue:
|
||||
move.l (%sp)+,%d2
|
||||
unlk %fp
|
||||
rts
|
||||
CFI_ENDPROC()
|
||||
.size ffi_call_SYSV,.-ffi_call_SYSV
|
||||
|
||||
.globl ffi_closure_SYSV
|
||||
.type ffi_closure_SYSV, @function
|
||||
.align 4
|
||||
|
||||
ffi_closure_SYSV:
|
||||
CFI_STARTPROC()
|
||||
link %fp,#-12
|
||||
CFI_OFFSET(14,-8)
|
||||
CFI_DEF_CFA(14,8)
|
||||
move.l %sp,-12(%fp)
|
||||
pea 8(%fp)
|
||||
pea -12(%fp)
|
||||
move.l %a0,-(%sp)
|
||||
#if !defined __PIC__
|
||||
jsr ffi_closure_SYSV_inner
|
||||
#else
|
||||
bsr.l ffi_closure_SYSV_inner@PLTPC
|
||||
#endif
|
||||
|
||||
lsr.l #1,%d0
|
||||
jne 1f
|
||||
jcc .Lcls_epilogue
|
||||
move.l -12(%fp),%d0
|
||||
.Lcls_epilogue:
|
||||
unlk %fp
|
||||
rts
|
||||
1:
|
||||
lea -12(%fp),%a0
|
||||
lsr.l #2,%d0
|
||||
jne 1f
|
||||
jcs .Lcls_ret_float
|
||||
move.l (%a0)+,%d0
|
||||
move.l (%a0),%d1
|
||||
jra .Lcls_epilogue
|
||||
.Lcls_ret_float:
|
||||
fmove.s (%a0),%fp0
|
||||
jra .Lcls_epilogue
|
||||
1:
|
||||
lsr.l #2,%d0
|
||||
jne 1f
|
||||
jcs .Lcls_ret_ldouble
|
||||
fmove.d (%a0),%fp0
|
||||
jra .Lcls_epilogue
|
||||
.Lcls_ret_ldouble:
|
||||
fmove.x (%a0),%fp0
|
||||
jra .Lcls_epilogue
|
||||
1:
|
||||
lsr.l #2,%d0
|
||||
jne .Lcls_ret_struct2
|
||||
jcs .Lcls_ret_struct1
|
||||
move.l (%a0),%a0
|
||||
move.l %a0,%d0
|
||||
jra .Lcls_epilogue
|
||||
.Lcls_ret_struct1:
|
||||
move.b (%a0),%d0
|
||||
jra .Lcls_epilogue
|
||||
.Lcls_ret_struct2:
|
||||
move.w (%a0),%d0
|
||||
jra .Lcls_epilogue
|
||||
CFI_ENDPROC()
|
||||
|
||||
.size ffi_closure_SYSV,.-ffi_closure_SYSV
|
||||
|
||||
.globl ffi_closure_struct_SYSV
|
||||
.type ffi_closure_struct_SYSV, @function
|
||||
.align 4
|
||||
|
||||
ffi_closure_struct_SYSV:
|
||||
CFI_STARTPROC()
|
||||
link %fp,#0
|
||||
CFI_OFFSET(14,-8)
|
||||
CFI_DEF_CFA(14,8)
|
||||
move.l %sp,-12(%fp)
|
||||
pea 8(%fp)
|
||||
move.l %a1,-(%sp)
|
||||
move.l %a0,-(%sp)
|
||||
#if !defined __PIC__
|
||||
jsr ffi_closure_SYSV_inner
|
||||
#else
|
||||
bsr.l ffi_closure_SYSV_inner@PLTPC
|
||||
#endif
|
||||
unlk %fp
|
||||
rts
|
||||
CFI_ENDPROC()
|
||||
.size ffi_closure_struct_SYSV,.-ffi_closure_struct_SYSV
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
278
src/m68k/ffi.c
Normal file
278
src/m68k/ffi.c
Normal file
@@ -0,0 +1,278 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c
|
||||
|
||||
m68k Foreign Function Interface
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <asm/cachectl.h>
|
||||
|
||||
void ffi_call_SYSV (extended_cif *,
|
||||
unsigned, unsigned,
|
||||
void *, void (*fn) ());
|
||||
void *ffi_prep_args (void *stack, extended_cif *ecif);
|
||||
void ffi_closure_SYSV (ffi_closure *);
|
||||
void ffi_closure_struct_SYSV (ffi_closure *);
|
||||
unsigned int ffi_closure_SYSV_inner (ffi_closure *closure,
|
||||
void *resp, void *args);
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack space has
|
||||
been allocated for the function's arguments. */
|
||||
|
||||
void *
|
||||
ffi_prep_args (void *stack, extended_cif *ecif)
|
||||
{
|
||||
unsigned int i;
|
||||
void **p_argv;
|
||||
char *argp;
|
||||
ffi_type **p_arg;
|
||||
void *struct_value_ptr;
|
||||
|
||||
argp = stack;
|
||||
|
||||
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
|
||||
&& !ecif->cif->flags)
|
||||
struct_value_ptr = ecif->rvalue;
|
||||
else
|
||||
struct_value_ptr = NULL;
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
i != 0;
|
||||
i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof (int))
|
||||
{
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
memcpy (argp + sizeof (int) - z, *p_argv, z);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
}
|
||||
z = sizeof (int);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (argp, *p_argv, z);
|
||||
|
||||
/* Align if necessary. */
|
||||
if ((sizeof(int) - 1) & z)
|
||||
z = ALIGN(z, sizeof(int));
|
||||
}
|
||||
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
|
||||
return struct_value_ptr;
|
||||
}
|
||||
|
||||
#define CIF_FLAGS_INT 1
|
||||
#define CIF_FLAGS_DINT 2
|
||||
#define CIF_FLAGS_FLOAT 4
|
||||
#define CIF_FLAGS_DOUBLE 8
|
||||
#define CIF_FLAGS_LDOUBLE 16
|
||||
#define CIF_FLAGS_POINTER 32
|
||||
#define CIF_FLAGS_STRUCT1 64
|
||||
#define CIF_FLAGS_STRUCT2 128
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep (ffi_cif *cif)
|
||||
{
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
cif->flags = 0;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
switch (cif->rtype->size)
|
||||
{
|
||||
case 1:
|
||||
cif->flags = CIF_FLAGS_STRUCT1;
|
||||
break;
|
||||
case 2:
|
||||
cif->flags = CIF_FLAGS_STRUCT2;
|
||||
break;
|
||||
case 4:
|
||||
cif->flags = CIF_FLAGS_INT;
|
||||
break;
|
||||
case 8:
|
||||
cif->flags = CIF_FLAGS_DINT;
|
||||
break;
|
||||
default:
|
||||
cif->flags = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
cif->flags = CIF_FLAGS_FLOAT;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags = CIF_FLAGS_DOUBLE;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
cif->flags = CIF_FLAGS_LDOUBLE;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
cif->flags = CIF_FLAGS_POINTER;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
cif->flags = CIF_FLAGS_DINT;
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags = CIF_FLAGS_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
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
|
||||
&& cif->rtype->size > 8)
|
||||
ecif.rvalue = alloca (cif->rtype->size);
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
ffi_call_SYSV (&ecif, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ffi_prep_incoming_args_SYSV (char *stack, void **avalue, ffi_cif *cif)
|
||||
{
|
||||
unsigned int i;
|
||||
void **p_argv;
|
||||
char *argp;
|
||||
ffi_type **p_arg;
|
||||
|
||||
argp = stack;
|
||||
p_argv = avalue;
|
||||
|
||||
for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
z = (*p_arg)->size;
|
||||
if (z <= 4)
|
||||
{
|
||||
*p_argv = (void *) (argp + 4 - z);
|
||||
|
||||
z = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
*p_argv = (void *) argp;
|
||||
|
||||
/* Align if necessary */
|
||||
if ((sizeof(int) - 1) & z)
|
||||
z = ALIGN(z, sizeof(int));
|
||||
}
|
||||
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int
|
||||
ffi_closure_SYSV_inner (ffi_closure *closure, void *resp, void *args)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
void **arg_area;
|
||||
|
||||
cif = closure->cif;
|
||||
arg_area = (void**) alloca (cif->nargs * sizeof (void *));
|
||||
|
||||
ffi_prep_incoming_args_SYSV(args, arg_area, cif);
|
||||
|
||||
(closure->fun) (cif, resp, arg_area, closure->user_data);
|
||||
|
||||
return cif->flags;
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
FFI_ASSERT (cif->abi == FFI_SYSV);
|
||||
|
||||
*(unsigned short *)closure->tramp = 0x207c;
|
||||
*(void **)(closure->tramp + 2) = codeloc;
|
||||
*(unsigned short *)(closure->tramp + 6) = 0x4ef9;
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT
|
||||
&& !cif->flags)
|
||||
*(void **)(closure->tramp + 8) = ffi_closure_struct_SYSV;
|
||||
else
|
||||
*(void **)(closure->tramp + 8) = ffi_closure_SYSV;
|
||||
|
||||
syscall(SYS_cacheflush, codeloc, FLUSH_SCOPE_LINE,
|
||||
FLUSH_CACHE_BOTH, FFI_TRAMPOLINE_SIZE);
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
49
src/m68k/ffitarget.h
Normal file
49
src/m68k/ffitarget.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for Motorola 68K.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_SYSV,
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 16
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
|
||||
234
src/m68k/sysv.S
Normal file
234
src/m68k/sysv.S
Normal file
@@ -0,0 +1,234 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 1998 Andreas Schwab
|
||||
Copyright (c) 2008 Red Hat, Inc.
|
||||
|
||||
m68k 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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
#ifdef HAVE_AS_CFI_PSEUDO_OP
|
||||
#define CFI_STARTPROC() .cfi_startproc
|
||||
#define CFI_OFFSET(reg,off) .cfi_offset reg,off
|
||||
#define CFI_DEF_CFA(reg,off) .cfi_def_cfa reg,off
|
||||
#define CFI_ENDPROC() .cfi_endproc
|
||||
#else
|
||||
#define CFI_STARTPROC()
|
||||
#define CFI_OFFSET(reg,off)
|
||||
#define CFI_DEF_CFA(reg,off)
|
||||
#define CFI_ENDPROC()
|
||||
#endif
|
||||
|
||||
.text
|
||||
|
||||
.globl ffi_call_SYSV
|
||||
.type ffi_call_SYSV,@function
|
||||
.align 4
|
||||
|
||||
ffi_call_SYSV:
|
||||
CFI_STARTPROC()
|
||||
link %fp,#0
|
||||
CFI_OFFSET(14,-8)
|
||||
CFI_DEF_CFA(14,8)
|
||||
move.l %d2,-(%sp)
|
||||
CFI_OFFSET(2,-12)
|
||||
|
||||
| Make room for all of the new args.
|
||||
sub.l 12(%fp),%sp
|
||||
|
||||
| Call ffi_prep_args
|
||||
move.l 8(%fp),-(%sp)
|
||||
pea 4(%sp)
|
||||
#if !defined __PIC__
|
||||
jsr ffi_prep_args
|
||||
#else
|
||||
bsr.l ffi_prep_args@PLTPC
|
||||
#endif
|
||||
addq.l #8,%sp
|
||||
|
||||
| Pass pointer to struct value, if any
|
||||
move.l %a0,%a1
|
||||
|
||||
| Call the function
|
||||
move.l 24(%fp),%a0
|
||||
jsr (%a0)
|
||||
|
||||
| Remove the space we pushed for the args
|
||||
add.l 12(%fp),%sp
|
||||
|
||||
| Load the pointer to storage for the return value
|
||||
move.l 20(%fp),%a1
|
||||
|
||||
| Load the return type code
|
||||
move.l 16(%fp),%d2
|
||||
|
||||
| If the return value pointer is NULL, assume no return value.
|
||||
tst.l %a1
|
||||
jbeq noretval
|
||||
|
||||
btst #0,%d2
|
||||
jbeq retlongint
|
||||
move.l %d0,(%a1)
|
||||
jbra epilogue
|
||||
|
||||
retlongint:
|
||||
btst #1,%d2
|
||||
jbeq retfloat
|
||||
move.l %d0,(%a1)
|
||||
move.l %d1,4(%a1)
|
||||
jbra epilogue
|
||||
|
||||
retfloat:
|
||||
btst #2,%d2
|
||||
jbeq retdouble
|
||||
fmove.s %fp0,(%a1)
|
||||
jbra epilogue
|
||||
|
||||
retdouble:
|
||||
btst #3,%d2
|
||||
jbeq retlongdouble
|
||||
fmove.d %fp0,(%a1)
|
||||
jbra epilogue
|
||||
|
||||
retlongdouble:
|
||||
btst #4,%d2
|
||||
jbeq retpointer
|
||||
fmove.x %fp0,(%a1)
|
||||
jbra epilogue
|
||||
|
||||
retpointer:
|
||||
btst #5,%d2
|
||||
jbeq retstruct1
|
||||
move.l %a0,(%a1)
|
||||
jbra epilogue
|
||||
|
||||
retstruct1:
|
||||
btst #6,%d2
|
||||
jbeq retstruct2
|
||||
move.b %d0,(%a1)
|
||||
jbra epilogue
|
||||
|
||||
retstruct2:
|
||||
btst #7,%d2
|
||||
jbeq noretval
|
||||
move.w %d0,(%a1)
|
||||
|
||||
noretval:
|
||||
epilogue:
|
||||
move.l (%sp)+,%d2
|
||||
unlk %fp
|
||||
rts
|
||||
CFI_ENDPROC()
|
||||
.size ffi_call_SYSV,.-ffi_call_SYSV
|
||||
|
||||
.globl ffi_closure_SYSV
|
||||
.type ffi_closure_SYSV, @function
|
||||
.align 4
|
||||
|
||||
ffi_closure_SYSV:
|
||||
CFI_STARTPROC()
|
||||
link %fp,#-12
|
||||
CFI_OFFSET(14,-8)
|
||||
CFI_DEF_CFA(14,8)
|
||||
move.l %sp,-12(%fp)
|
||||
pea 8(%fp)
|
||||
pea -12(%fp)
|
||||
move.l %a0,-(%sp)
|
||||
#if !defined __PIC__
|
||||
jsr ffi_closure_SYSV_inner
|
||||
#else
|
||||
bsr.l ffi_closure_SYSV_inner@PLTPC
|
||||
#endif
|
||||
|
||||
lsr.l #1,%d0
|
||||
jne 1f
|
||||
jcc .Lcls_epilogue
|
||||
move.l -12(%fp),%d0
|
||||
.Lcls_epilogue:
|
||||
unlk %fp
|
||||
rts
|
||||
1:
|
||||
lea -12(%fp),%a0
|
||||
lsr.l #2,%d0
|
||||
jne 1f
|
||||
jcs .Lcls_ret_float
|
||||
move.l (%a0)+,%d0
|
||||
move.l (%a0),%d1
|
||||
jra .Lcls_epilogue
|
||||
.Lcls_ret_float:
|
||||
fmove.s (%a0),%fp0
|
||||
jra .Lcls_epilogue
|
||||
1:
|
||||
lsr.l #2,%d0
|
||||
jne 1f
|
||||
jcs .Lcls_ret_ldouble
|
||||
fmove.d (%a0),%fp0
|
||||
jra .Lcls_epilogue
|
||||
.Lcls_ret_ldouble:
|
||||
fmove.x (%a0),%fp0
|
||||
jra .Lcls_epilogue
|
||||
1:
|
||||
lsr.l #2,%d0
|
||||
jne .Lcls_ret_struct2
|
||||
jcs .Lcls_ret_struct1
|
||||
move.l (%a0),%a0
|
||||
move.l %a0,%d0
|
||||
jra .Lcls_epilogue
|
||||
.Lcls_ret_struct1:
|
||||
move.b (%a0),%d0
|
||||
jra .Lcls_epilogue
|
||||
.Lcls_ret_struct2:
|
||||
move.w (%a0),%d0
|
||||
jra .Lcls_epilogue
|
||||
CFI_ENDPROC()
|
||||
|
||||
.size ffi_closure_SYSV,.-ffi_closure_SYSV
|
||||
|
||||
.globl ffi_closure_struct_SYSV
|
||||
.type ffi_closure_struct_SYSV, @function
|
||||
.align 4
|
||||
|
||||
ffi_closure_struct_SYSV:
|
||||
CFI_STARTPROC()
|
||||
link %fp,#0
|
||||
CFI_OFFSET(14,-8)
|
||||
CFI_DEF_CFA(14,8)
|
||||
move.l %sp,-12(%fp)
|
||||
pea 8(%fp)
|
||||
move.l %a1,-(%sp)
|
||||
move.l %a0,-(%sp)
|
||||
#if !defined __PIC__
|
||||
jsr ffi_closure_SYSV_inner
|
||||
#else
|
||||
bsr.l ffi_closure_SYSV_inner@PLTPC
|
||||
#endif
|
||||
unlk %fp
|
||||
rts
|
||||
CFI_ENDPROC()
|
||||
.size ffi_closure_struct_SYSV,.-ffi_closure_struct_SYSV
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
164
src/mips/.svn/entries
Normal file
164
src/mips/.svn/entries
Normal file
@@ -0,0 +1,164 @@
|
||||
10
|
||||
|
||||
dir
|
||||
152280
|
||||
svn://gcc.gnu.org/svn/gcc/trunk/libffi/src/mips
|
||||
svn://gcc.gnu.org/svn/gcc
|
||||
|
||||
|
||||
|
||||
2009-09-15T17:15:33.045042Z
|
||||
151726
|
||||
daney
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
138bc75d-0d04-0410-961f-82ee72b054a4
|
||||
|
||||
ffitarget.h
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-09-16T16:25:59.000000Z
|
||||
fdf13476bd3e53815092fde3494d8fc9
|
||||
2009-09-15T17:15:33.045042Z
|
||||
151726
|
||||
daney
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
5878
|
||||
|
||||
n32.S
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-09-16T16:25:59.000000Z
|
||||
142328c284156e2c2ea05bbcbf19a163
|
||||
2009-09-15T17:15:33.045042Z
|
||||
151726
|
||||
daney
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
14437
|
||||
|
||||
o32.S
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:03.000000Z
|
||||
46fc9e546cfb341f1ebf869bed97ebd4
|
||||
2009-06-04T15:11:12.475454Z
|
||||
148171
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
10586
|
||||
|
||||
ffi.c
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-09-16T16:25:59.000000Z
|
||||
8ab6839e93489a8417539b6953934de1
|
||||
2009-09-15T17:15:33.045042Z
|
||||
151726
|
||||
daney
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
25747
|
||||
|
||||
1022
src/mips/.svn/text-base/ffi.c.svn-base
Normal file
1022
src/mips/.svn/text-base/ffi.c.svn-base
Normal file
File diff suppressed because it is too large
Load Diff
221
src/mips/.svn/text-base/ffitarget.h.svn-base
Normal file
221
src/mips/.svn/text-base/ffitarget.h.svn-base
Normal file
@@ -0,0 +1,221 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for MIPS.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
#ifdef linux
|
||||
#include <asm/sgidefs.h>
|
||||
# ifndef _ABIN32
|
||||
# define _ABIN32 _MIPS_SIM_NABI32
|
||||
# endif
|
||||
# ifndef _ABI64
|
||||
# define _ABI64 _MIPS_SIM_ABI64
|
||||
# endif
|
||||
# ifndef _ABIO32
|
||||
# define _ABIO32 _MIPS_SIM_ABI32
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(_MIPS_SIM)
|
||||
-- something is very wrong --
|
||||
#else
|
||||
# if (_MIPS_SIM==_ABIN32 && defined(_ABIN32)) || (_MIPS_SIM==_ABI64 && defined(_ABI64))
|
||||
# define FFI_MIPS_N32
|
||||
# else
|
||||
# if (_MIPS_SIM==_ABIO32 && defined(_ABIO32))
|
||||
# define FFI_MIPS_O32
|
||||
# else
|
||||
-- this is an unsupported platform --
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef FFI_MIPS_O32
|
||||
/* O32 stack frames have 32bit integer args */
|
||||
# define FFI_SIZEOF_ARG 4
|
||||
#else
|
||||
/* N32 and N64 frames have 64bit integer args */
|
||||
# define FFI_SIZEOF_ARG 8
|
||||
# if _MIPS_SIM == _ABIN32
|
||||
# define FFI_SIZEOF_JAVA_RAW 4
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define FFI_FLAG_BITS 2
|
||||
|
||||
/* SGI's strange assembler requires that we multiply by 4 rather
|
||||
than shift left by FFI_FLAG_BITS */
|
||||
|
||||
#define FFI_ARGS_D FFI_TYPE_DOUBLE
|
||||
#define FFI_ARGS_F FFI_TYPE_FLOAT
|
||||
#define FFI_ARGS_DD FFI_TYPE_DOUBLE * 4 + FFI_TYPE_DOUBLE
|
||||
#define FFI_ARGS_FF FFI_TYPE_FLOAT * 4 + FFI_TYPE_FLOAT
|
||||
#define FFI_ARGS_FD FFI_TYPE_DOUBLE * 4 + FFI_TYPE_FLOAT
|
||||
#define FFI_ARGS_DF FFI_TYPE_FLOAT * 4 + FFI_TYPE_DOUBLE
|
||||
|
||||
/* Needed for N32 structure returns */
|
||||
#define FFI_TYPE_SMALLSTRUCT FFI_TYPE_UINT8
|
||||
#define FFI_TYPE_SMALLSTRUCT2 FFI_TYPE_SINT8
|
||||
|
||||
#if 0
|
||||
/* The SGI assembler can't handle this.. */
|
||||
#define FFI_TYPE_STRUCT_DD (( FFI_ARGS_DD ) << 4) + FFI_TYPE_STRUCT
|
||||
/* (and so on) */
|
||||
#else
|
||||
/* ...so we calculate these by hand! */
|
||||
#define FFI_TYPE_STRUCT_D 61
|
||||
#define FFI_TYPE_STRUCT_F 45
|
||||
#define FFI_TYPE_STRUCT_DD 253
|
||||
#define FFI_TYPE_STRUCT_FF 173
|
||||
#define FFI_TYPE_STRUCT_FD 237
|
||||
#define FFI_TYPE_STRUCT_DF 189
|
||||
#define FFI_TYPE_STRUCT_SMALL 93
|
||||
#define FFI_TYPE_STRUCT_SMALL2 109
|
||||
|
||||
/* and for n32 soft float, add 16 * 2^4 */
|
||||
#define FFI_TYPE_STRUCT_D_SOFT 317
|
||||
#define FFI_TYPE_STRUCT_F_SOFT 301
|
||||
#define FFI_TYPE_STRUCT_DD_SOFT 509
|
||||
#define FFI_TYPE_STRUCT_FF_SOFT 429
|
||||
#define FFI_TYPE_STRUCT_FD_SOFT 493
|
||||
#define FFI_TYPE_STRUCT_DF_SOFT 445
|
||||
#define FFI_TYPE_STRUCT_SOFT 16
|
||||
#endif
|
||||
|
||||
#ifdef LIBFFI_ASM
|
||||
#define v0 $2
|
||||
#define v1 $3
|
||||
#define a0 $4
|
||||
#define a1 $5
|
||||
#define a2 $6
|
||||
#define a3 $7
|
||||
#define a4 $8
|
||||
#define a5 $9
|
||||
#define a6 $10
|
||||
#define a7 $11
|
||||
#define t0 $8
|
||||
#define t1 $9
|
||||
#define t2 $10
|
||||
#define t3 $11
|
||||
#define t4 $12
|
||||
#define t5 $13
|
||||
#define t6 $14
|
||||
#define t7 $15
|
||||
#define t8 $24
|
||||
#define t9 $25
|
||||
#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
|
||||
#else /* !FFI_MIPS_O32 */
|
||||
# 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
|
||||
/* O32 stack frames have 32bit integer args */
|
||||
typedef unsigned int ffi_arg __attribute__((__mode__(__SI__)));
|
||||
typedef signed int ffi_sarg __attribute__((__mode__(__SI__)));
|
||||
#else
|
||||
/* N32 and N64 frames have 64bit integer args */
|
||||
typedef unsigned int ffi_arg __attribute__((__mode__(__DI__)));
|
||||
typedef signed int ffi_sarg __attribute__((__mode__(__DI__)));
|
||||
#endif
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_O32,
|
||||
FFI_N32,
|
||||
FFI_N64,
|
||||
FFI_O32_SOFT_FLOAT,
|
||||
FFI_N32_SOFT_FLOAT,
|
||||
FFI_N64_SOFT_FLOAT,
|
||||
|
||||
#ifdef FFI_MIPS_O32
|
||||
#ifdef __mips_soft_float
|
||||
FFI_DEFAULT_ABI = FFI_O32_SOFT_FLOAT,
|
||||
#else
|
||||
FFI_DEFAULT_ABI = FFI_O32,
|
||||
#endif
|
||||
#else
|
||||
# if _MIPS_SIM==_ABI64
|
||||
# ifdef __mips_soft_float
|
||||
FFI_DEFAULT_ABI = FFI_N64_SOFT_FLOAT,
|
||||
# else
|
||||
FFI_DEFAULT_ABI = FFI_N64,
|
||||
# endif
|
||||
# else
|
||||
# ifdef __mips_soft_float
|
||||
FFI_DEFAULT_ABI = FFI_N32_SOFT_FLOAT,
|
||||
# else
|
||||
FFI_DEFAULT_ABI = FFI_N32,
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
|
||||
#define FFI_EXTRA_CIF_FIELDS unsigned rstruct_flag
|
||||
#endif /* !LIBFFI_ASM */
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#if defined(FFI_MIPS_O32)
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 20
|
||||
#else
|
||||
/* 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
|
||||
|
||||
#endif
|
||||
|
||||
587
src/mips/.svn/text-base/n32.S.svn-base
Normal file
587
src/mips/.svn/text-base/n32.S.svn-base
Normal file
@@ -0,0 +1,587 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
n32.S - Copyright (c) 1996, 1998, 2005 Red Hat, Inc.
|
||||
|
||||
MIPS 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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
/* Only build this code if we are compiling for n32 */
|
||||
|
||||
#if defined(FFI_MIPS_N32)
|
||||
|
||||
#define callback a0
|
||||
#define bytes a2
|
||||
#define flags a3
|
||||
#define raddr a4
|
||||
#define fn a5
|
||||
|
||||
#define SIZEOF_FRAME ( 8 * FFI_SIZEOF_ARG )
|
||||
|
||||
.abicalls
|
||||
.text
|
||||
.align 2
|
||||
.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
|
||||
REG_S raddr, 4*FFI_SIZEOF_ARG($fp) # raddr
|
||||
REG_S fn, 5*FFI_SIZEOF_ARG($fp) # fn
|
||||
|
||||
# Allocate at least 4 words in the argstack
|
||||
move v0, bytes
|
||||
bge bytes, 4 * FFI_SIZEOF_ARG, bigger
|
||||
LI v0, 4 * FFI_SIZEOF_ARG
|
||||
b sixteen
|
||||
|
||||
bigger:
|
||||
ADDU t4, v0, 2 * FFI_SIZEOF_ARG -1 # make sure it is aligned
|
||||
and v0, t4, -2 * FFI_SIZEOF_ARG # to a proper boundry.
|
||||
|
||||
sixteen:
|
||||
SUBU $sp, $sp, v0 # move the stack pointer to reflect the
|
||||
# arg space
|
||||
|
||||
move a0, $sp # 4 * FFI_SIZEOF_ARG
|
||||
ADDU a3, $fp, 3 * FFI_SIZEOF_ARG
|
||||
|
||||
# Call ffi_prep_args
|
||||
jal t9
|
||||
|
||||
# Copy the stack pointer to t9
|
||||
move t9, $sp
|
||||
|
||||
# Fix the stack if there are more than 8 64bit slots worth
|
||||
# of arguments.
|
||||
|
||||
# Load the number of bytes
|
||||
REG_L t6, 2*FFI_SIZEOF_ARG($fp)
|
||||
|
||||
# Is it bigger than 8 * FFI_SIZEOF_ARG?
|
||||
daddiu t8, t6, -(8 * FFI_SIZEOF_ARG)
|
||||
bltz t8, loadregs
|
||||
|
||||
ADDU t9, t9, t8
|
||||
|
||||
loadregs:
|
||||
|
||||
REG_L t6, 3*FFI_SIZEOF_ARG($fp) # load the flags word into t6.
|
||||
|
||||
and t4, t6, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg1_floatp
|
||||
REG_L a0, 0*FFI_SIZEOF_ARG(t9)
|
||||
b arg1_next
|
||||
arg1_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg1_doublep
|
||||
l.s $f12, 0*FFI_SIZEOF_ARG(t9)
|
||||
b arg1_next
|
||||
arg1_doublep:
|
||||
l.d $f12, 0*FFI_SIZEOF_ARG(t9)
|
||||
arg1_next:
|
||||
|
||||
SRL t4, t6, 1*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg2_floatp
|
||||
REG_L a1, 1*FFI_SIZEOF_ARG(t9)
|
||||
b arg2_next
|
||||
arg2_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg2_doublep
|
||||
l.s $f13, 1*FFI_SIZEOF_ARG(t9)
|
||||
b arg2_next
|
||||
arg2_doublep:
|
||||
l.d $f13, 1*FFI_SIZEOF_ARG(t9)
|
||||
arg2_next:
|
||||
|
||||
SRL t4, t6, 2*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg3_floatp
|
||||
REG_L a2, 2*FFI_SIZEOF_ARG(t9)
|
||||
b arg3_next
|
||||
arg3_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg3_doublep
|
||||
l.s $f14, 2*FFI_SIZEOF_ARG(t9)
|
||||
b arg3_next
|
||||
arg3_doublep:
|
||||
l.d $f14, 2*FFI_SIZEOF_ARG(t9)
|
||||
arg3_next:
|
||||
|
||||
SRL t4, t6, 3*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg4_floatp
|
||||
REG_L a3, 3*FFI_SIZEOF_ARG(t9)
|
||||
b arg4_next
|
||||
arg4_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg4_doublep
|
||||
l.s $f15, 3*FFI_SIZEOF_ARG(t9)
|
||||
b arg4_next
|
||||
arg4_doublep:
|
||||
l.d $f15, 3*FFI_SIZEOF_ARG(t9)
|
||||
arg4_next:
|
||||
|
||||
SRL t4, t6, 4*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg5_floatp
|
||||
REG_L a4, 4*FFI_SIZEOF_ARG(t9)
|
||||
b arg5_next
|
||||
arg5_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg5_doublep
|
||||
l.s $f16, 4*FFI_SIZEOF_ARG(t9)
|
||||
b arg5_next
|
||||
arg5_doublep:
|
||||
l.d $f16, 4*FFI_SIZEOF_ARG(t9)
|
||||
arg5_next:
|
||||
|
||||
SRL t4, t6, 5*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg6_floatp
|
||||
REG_L a5, 5*FFI_SIZEOF_ARG(t9)
|
||||
b arg6_next
|
||||
arg6_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg6_doublep
|
||||
l.s $f17, 5*FFI_SIZEOF_ARG(t9)
|
||||
b arg6_next
|
||||
arg6_doublep:
|
||||
l.d $f17, 5*FFI_SIZEOF_ARG(t9)
|
||||
arg6_next:
|
||||
|
||||
SRL t4, t6, 6*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg7_floatp
|
||||
REG_L a6, 6*FFI_SIZEOF_ARG(t9)
|
||||
b arg7_next
|
||||
arg7_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg7_doublep
|
||||
l.s $f18, 6*FFI_SIZEOF_ARG(t9)
|
||||
b arg7_next
|
||||
arg7_doublep:
|
||||
l.d $f18, 6*FFI_SIZEOF_ARG(t9)
|
||||
arg7_next:
|
||||
|
||||
SRL t4, t6, 7*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg8_floatp
|
||||
REG_L a7, 7*FFI_SIZEOF_ARG(t9)
|
||||
b arg8_next
|
||||
arg8_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg8_doublep
|
||||
l.s $f19, 7*FFI_SIZEOF_ARG(t9)
|
||||
b arg8_next
|
||||
arg8_doublep:
|
||||
l.d $f19, 7*FFI_SIZEOF_ARG(t9)
|
||||
arg8_next:
|
||||
|
||||
callit:
|
||||
# Load the function pointer
|
||||
REG_L t9, 5*FFI_SIZEOF_ARG($fp)
|
||||
|
||||
# If the return value pointer is NULL, assume no return value.
|
||||
REG_L t5, 4*FFI_SIZEOF_ARG($fp)
|
||||
beqz t5, noretval
|
||||
|
||||
# Shift the return type flag over
|
||||
SRL t6, 8*FFI_FLAG_BITS
|
||||
|
||||
beq t6, FFI_TYPE_SINT32, retint
|
||||
bne t6, FFI_TYPE_INT, retfloat
|
||||
retint:
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
REG_S v0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retfloat:
|
||||
bne t6, FFI_TYPE_FLOAT, retdouble
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.s $f0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retdouble:
|
||||
bne t6, FFI_TYPE_DOUBLE, retstruct_d
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.d $f0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_d:
|
||||
bne t6, FFI_TYPE_STRUCT_D, retstruct_f
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.d $f0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_f:
|
||||
bne t6, FFI_TYPE_STRUCT_F, retstruct_d_d
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.s $f0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_d_d:
|
||||
bne t6, FFI_TYPE_STRUCT_DD, retstruct_f_f
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.d $f0, 0(t4)
|
||||
s.d $f2, 8(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_f_f:
|
||||
bne t6, FFI_TYPE_STRUCT_FF, retstruct_d_f
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.s $f0, 0(t4)
|
||||
s.s $f2, 4(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_d_f:
|
||||
bne t6, FFI_TYPE_STRUCT_DF, retstruct_f_d
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.d $f0, 0(t4)
|
||||
s.s $f2, 8(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_f_d:
|
||||
bne t6, FFI_TYPE_STRUCT_FD, retstruct_d_soft
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.s $f0, 0(t4)
|
||||
s.d $f2, 8(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_d_soft:
|
||||
bne t6, FFI_TYPE_STRUCT_D_SOFT, retstruct_f_soft
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
sd v0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_f_soft:
|
||||
bne t6, FFI_TYPE_STRUCT_F_SOFT, retstruct_d_d_soft
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
sw v0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_d_d_soft:
|
||||
bne t6, FFI_TYPE_STRUCT_DD_SOFT, retstruct_f_f_soft
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
sd v0, 0(t4)
|
||||
sd v1, 8(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_f_f_soft:
|
||||
bne t6, FFI_TYPE_STRUCT_FF_SOFT, retstruct_d_f_soft
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
sw v0, 0(t4)
|
||||
sw v1, 4(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_d_f_soft:
|
||||
bne t6, FFI_TYPE_STRUCT_DF_SOFT, retstruct_f_d_soft
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
sd v0, 0(t4)
|
||||
sw v1, 8(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_f_d_soft:
|
||||
bne t6, FFI_TYPE_STRUCT_FD_SOFT, retstruct_small
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
sw v0, 0(t4)
|
||||
sd v1, 8(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_small:
|
||||
bne t6, FFI_TYPE_STRUCT_SMALL, retstruct_small2
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
REG_S v0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_small2:
|
||||
bne t6, FFI_TYPE_STRUCT_SMALL2, retstruct
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
REG_S v0, 0(t4)
|
||||
REG_S v1, 8(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct:
|
||||
noretval:
|
||||
jal t9
|
||||
|
||||
# Epilogue
|
||||
epilogue:
|
||||
move $sp, $fp
|
||||
REG_L $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Restore frame pointer
|
||||
REG_L ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp) # Restore return address
|
||||
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_SINT32, cls_retint
|
||||
lw v0, V0_OFF2($sp)
|
||||
b cls_epilogue
|
||||
|
||||
cls_retint:
|
||||
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
|
||||
381
src/mips/.svn/text-base/o32.S.svn-base
Normal file
381
src/mips/.svn/text-base/o32.S.svn-base
Normal file
@@ -0,0 +1,381 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
o32.S - Copyright (c) 1996, 1998, 2005 Red Hat, Inc.
|
||||
|
||||
MIPS 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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
/* Only build this code if we are compiling for o32 */
|
||||
|
||||
#if defined(FFI_MIPS_O32)
|
||||
|
||||
#define callback a0
|
||||
#define bytes a2
|
||||
#define flags a3
|
||||
|
||||
#define SIZEOF_FRAME (4 * FFI_SIZEOF_ARG + 2 * FFI_SIZEOF_ARG)
|
||||
#define A3_OFF (SIZEOF_FRAME + 3 * FFI_SIZEOF_ARG)
|
||||
#define FP_OFF (SIZEOF_FRAME - 2 * FFI_SIZEOF_ARG)
|
||||
#define RA_OFF (SIZEOF_FRAME - 1 * FFI_SIZEOF_ARG)
|
||||
|
||||
.abicalls
|
||||
.text
|
||||
.align 2
|
||||
.globl ffi_call_O32
|
||||
.ent ffi_call_O32
|
||||
ffi_call_O32:
|
||||
$LFB0:
|
||||
# Prologue
|
||||
SUBU $sp, SIZEOF_FRAME # Frame size
|
||||
$LCFI0:
|
||||
REG_S $fp, FP_OFF($sp) # Save frame pointer
|
||||
$LCFI1:
|
||||
REG_S ra, RA_OFF($sp) # Save return address
|
||||
$LCFI2:
|
||||
move $fp, $sp
|
||||
|
||||
$LCFI3:
|
||||
move t9, callback # callback function pointer
|
||||
REG_S flags, A3_OFF($fp) # flags
|
||||
|
||||
# Allocate at least 4 words in the argstack
|
||||
LI v0, 4 * FFI_SIZEOF_ARG
|
||||
blt bytes, v0, sixteen
|
||||
|
||||
ADDU v0, bytes, 7 # make sure it is aligned
|
||||
and v0, -8 # to an 8 byte boundry
|
||||
|
||||
sixteen:
|
||||
SUBU $sp, v0 # move the stack pointer to reflect the
|
||||
# arg space
|
||||
|
||||
ADDU a0, $sp, 4 * FFI_SIZEOF_ARG
|
||||
|
||||
jalr t9
|
||||
|
||||
REG_L t0, A3_OFF($fp) # load the flags word
|
||||
SRL t2, t0, 4 # shift our arg info
|
||||
and t0, ((1<<4)-1) # mask out the return type
|
||||
|
||||
ADDU $sp, 4 * FFI_SIZEOF_ARG # adjust $sp to new args
|
||||
|
||||
bnez t0, pass_d # make it quick for int
|
||||
REG_L a0, 0*FFI_SIZEOF_ARG($sp) # just go ahead and load the
|
||||
REG_L a1, 1*FFI_SIZEOF_ARG($sp) # four regs.
|
||||
REG_L a2, 2*FFI_SIZEOF_ARG($sp)
|
||||
REG_L a3, 3*FFI_SIZEOF_ARG($sp)
|
||||
b call_it
|
||||
|
||||
pass_d:
|
||||
bne t0, FFI_ARGS_D, pass_f
|
||||
l.d $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args
|
||||
REG_L a2, 2*FFI_SIZEOF_ARG($sp) # passing a double
|
||||
REG_L a3, 3*FFI_SIZEOF_ARG($sp)
|
||||
b call_it
|
||||
|
||||
pass_f:
|
||||
bne t0, FFI_ARGS_F, pass_d_d
|
||||
l.s $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args
|
||||
REG_L a1, 1*FFI_SIZEOF_ARG($sp) # passing a float
|
||||
REG_L a2, 2*FFI_SIZEOF_ARG($sp)
|
||||
REG_L a3, 3*FFI_SIZEOF_ARG($sp)
|
||||
b call_it
|
||||
|
||||
pass_d_d:
|
||||
bne t0, FFI_ARGS_DD, pass_f_f
|
||||
l.d $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args
|
||||
l.d $f14, 2*FFI_SIZEOF_ARG($sp) # passing two doubles
|
||||
b call_it
|
||||
|
||||
pass_f_f:
|
||||
bne t0, FFI_ARGS_FF, pass_d_f
|
||||
l.s $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args
|
||||
l.s $f14, 1*FFI_SIZEOF_ARG($sp) # passing two floats
|
||||
REG_L a2, 2*FFI_SIZEOF_ARG($sp)
|
||||
REG_L a3, 3*FFI_SIZEOF_ARG($sp)
|
||||
b call_it
|
||||
|
||||
pass_d_f:
|
||||
bne t0, FFI_ARGS_DF, pass_f_d
|
||||
l.d $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args
|
||||
l.s $f14, 2*FFI_SIZEOF_ARG($sp) # passing double and float
|
||||
REG_L a3, 3*FFI_SIZEOF_ARG($sp)
|
||||
b call_it
|
||||
|
||||
pass_f_d:
|
||||
# assume that the only other combination must be float then double
|
||||
# bne t0, FFI_ARGS_F_D, call_it
|
||||
l.s $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args
|
||||
l.d $f14, 2*FFI_SIZEOF_ARG($sp) # passing double and float
|
||||
|
||||
call_it:
|
||||
# Load the function pointer
|
||||
REG_L t9, SIZEOF_FRAME + 5*FFI_SIZEOF_ARG($fp)
|
||||
|
||||
# If the return value pointer is NULL, assume no return value.
|
||||
REG_L t1, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
|
||||
beqz t1, noretval
|
||||
|
||||
bne t2, FFI_TYPE_INT, retlonglong
|
||||
jalr t9
|
||||
REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
|
||||
REG_S v0, 0(t0)
|
||||
b epilogue
|
||||
|
||||
retlonglong:
|
||||
# Really any 64-bit int, signed or not.
|
||||
bne t2, FFI_TYPE_UINT64, retfloat
|
||||
jalr t9
|
||||
REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
|
||||
REG_S v1, 4(t0)
|
||||
REG_S v0, 0(t0)
|
||||
b epilogue
|
||||
|
||||
retfloat:
|
||||
bne t2, FFI_TYPE_FLOAT, retdouble
|
||||
jalr t9
|
||||
REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
|
||||
s.s $f0, 0(t0)
|
||||
b epilogue
|
||||
|
||||
retdouble:
|
||||
bne t2, FFI_TYPE_DOUBLE, noretval
|
||||
jalr t9
|
||||
REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
|
||||
s.d $f0, 0(t0)
|
||||
b epilogue
|
||||
|
||||
noretval:
|
||||
jalr t9
|
||||
|
||||
# Epilogue
|
||||
epilogue:
|
||||
move $sp, $fp
|
||||
REG_L $fp, FP_OFF($sp) # Restore frame pointer
|
||||
REG_L ra, RA_OFF($sp) # Restore return address
|
||||
ADDU $sp, SIZEOF_FRAME # Fix stack pointer
|
||||
j ra
|
||||
|
||||
$LFE0:
|
||||
.end ffi_call_O32
|
||||
|
||||
|
||||
/* ffi_closure_O32. Expects address of the passed-in ffi_closure
|
||||
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:
|
||||
|
||||
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)
|
||||
#define A3_OFF2 (SIZEOF_FRAME2 + 3 * FFI_SIZEOF_ARG)
|
||||
#define A2_OFF2 (SIZEOF_FRAME2 + 2 * FFI_SIZEOF_ARG)
|
||||
#define A1_OFF2 (SIZEOF_FRAME2 + 1 * FFI_SIZEOF_ARG)
|
||||
#define A0_OFF2 (SIZEOF_FRAME2 + 0 * FFI_SIZEOF_ARG)
|
||||
#define RA_OFF2 (SIZEOF_FRAME2 - 1 * FFI_SIZEOF_ARG)
|
||||
#define FP_OFF2 (SIZEOF_FRAME2 - 2 * FFI_SIZEOF_ARG)
|
||||
#define S0_OFF2 (SIZEOF_FRAME2 - 3 * FFI_SIZEOF_ARG)
|
||||
#define GP_OFF2 (SIZEOF_FRAME2 - 4 * FFI_SIZEOF_ARG)
|
||||
#define V1_OFF2 (SIZEOF_FRAME2 - 5 * FFI_SIZEOF_ARG)
|
||||
#define V0_OFF2 (SIZEOF_FRAME2 - 6 * FFI_SIZEOF_ARG)
|
||||
#define FA_1_1_OFF2 (SIZEOF_FRAME2 - 7 * FFI_SIZEOF_ARG)
|
||||
#define FA_1_0_OFF2 (SIZEOF_FRAME2 - 8 * FFI_SIZEOF_ARG)
|
||||
#define FA_0_1_OFF2 (SIZEOF_FRAME2 - 9 * FFI_SIZEOF_ARG)
|
||||
#define FA_0_0_OFF2 (SIZEOF_FRAME2 - 10 * FFI_SIZEOF_ARG)
|
||||
|
||||
.text
|
||||
.align 2
|
||||
.globl ffi_closure_O32
|
||||
.ent ffi_closure_O32
|
||||
ffi_closure_O32:
|
||||
$LFB1:
|
||||
# Prologue
|
||||
.frame $fp, SIZEOF_FRAME2, ra
|
||||
.set noreorder
|
||||
.cpload t9
|
||||
.set reorder
|
||||
SUBU $sp, SIZEOF_FRAME2
|
||||
.cprestore GP_OFF2
|
||||
$LCFI4:
|
||||
REG_S $16, S0_OFF2($sp) # Save s0
|
||||
REG_S $fp, FP_OFF2($sp) # Save frame pointer
|
||||
REG_S ra, RA_OFF2($sp) # Save return address
|
||||
$LCFI6:
|
||||
move $fp, $sp
|
||||
|
||||
$LCFI7:
|
||||
# Store all possible argument registers. If there are more than
|
||||
# four arguments, then they are stored above where we put a3.
|
||||
REG_S a0, A0_OFF2($fp)
|
||||
REG_S a1, A1_OFF2($fp)
|
||||
REG_S a2, A2_OFF2($fp)
|
||||
REG_S a3, A3_OFF2($fp)
|
||||
|
||||
# Load ABI enum to s0
|
||||
REG_L $16, 20($12) # cif pointer follows tramp.
|
||||
REG_L $16, 0($16) # abi is first member.
|
||||
|
||||
li $13, 1 # FFI_O32
|
||||
bne $16, $13, 1f # Skip fp save if FFI_O32_SOFT_FLOAT
|
||||
|
||||
# Store all possible float/double registers.
|
||||
s.d $f12, FA_0_0_OFF2($fp)
|
||||
s.d $f14, FA_1_0_OFF2($fp)
|
||||
1:
|
||||
# Call ffi_closure_mips_inner_O32 to do the work.
|
||||
la t9, ffi_closure_mips_inner_O32
|
||||
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
|
||||
jalr t9
|
||||
|
||||
# Load the return value into the appropriate register.
|
||||
move $8, $2
|
||||
li $9, FFI_TYPE_VOID
|
||||
beq $8, $9, closure_done
|
||||
|
||||
li $13, 1 # FFI_O32
|
||||
bne $16, $13, 1f # Skip fp restore if FFI_O32_SOFT_FLOAT
|
||||
|
||||
li $9, FFI_TYPE_FLOAT
|
||||
l.s $f0, V0_OFF2($fp)
|
||||
beq $8, $9, closure_done
|
||||
|
||||
li $9, FFI_TYPE_DOUBLE
|
||||
l.d $f0, V0_OFF2($fp)
|
||||
beq $8, $9, closure_done
|
||||
1:
|
||||
REG_L $3, V1_OFF2($fp)
|
||||
REG_L $2, V0_OFF2($fp)
|
||||
|
||||
closure_done:
|
||||
# Epilogue
|
||||
move $sp, $fp
|
||||
REG_L $16, S0_OFF2($sp) # Restore s0
|
||||
REG_L $fp, FP_OFF2($sp) # Restore frame pointer
|
||||
REG_L ra, RA_OFF2($sp) # Restore return address
|
||||
ADDU $sp, SIZEOF_FRAME2
|
||||
j ra
|
||||
$LFE1:
|
||||
.end ffi_closure_O32
|
||||
|
||||
/* DWARF-2 unwind info. */
|
||||
|
||||
.section .eh_frame,"a",@progbits
|
||||
$Lframe0:
|
||||
.4byte $LECIE0-$LSCIE0 # Length of Common Information Entry
|
||||
$LSCIE0:
|
||||
.4byte 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.uleb128 0x1 # CIE Code Alignment Factor
|
||||
.sleb128 4 # CIE Data Alignment Factor
|
||||
.byte 0x1f # CIE RA Column
|
||||
.uleb128 0x1 # Augmentation size
|
||||
.byte 0x00 # FDE Encoding (absptr)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1d
|
||||
.uleb128 0x0
|
||||
.align 2
|
||||
$LECIE0:
|
||||
$LSFDE0:
|
||||
.4byte $LEFDE0-$LASFDE0 # FDE Length
|
||||
$LASFDE0:
|
||||
.4byte $LASFDE0-$Lframe0 # FDE CIE offset
|
||||
.4byte $LFB0 # FDE initial location
|
||||
.4byte $LFE0-$LFB0 # FDE address range
|
||||
.uleb128 0x0 # Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI0-$LFB0
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 0x18
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI2-$LCFI0
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x1e # $fp
|
||||
.sleb128 -2 # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp)
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x1f # $ra
|
||||
.sleb128 -1 # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp)
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI3-$LCFI2
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1e
|
||||
.uleb128 0x18
|
||||
.align 2
|
||||
$LEFDE0:
|
||||
$LSFDE1:
|
||||
.4byte $LEFDE1-$LASFDE1 # FDE Length
|
||||
$LASFDE1:
|
||||
.4byte $LASFDE1-$Lframe0 # FDE CIE offset
|
||||
.4byte $LFB1 # FDE initial location
|
||||
.4byte $LFE1-$LFB1 # FDE address range
|
||||
.uleb128 0x0 # Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI4-$LFB1
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 0x38
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI6-$LCFI4
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x10 # $16
|
||||
.sleb128 -3 # SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp)
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x1e # $fp
|
||||
.sleb128 -2 # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp)
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x1f # $ra
|
||||
.sleb128 -1 # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp)
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI7-$LCFI6
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1e
|
||||
.uleb128 0x38
|
||||
.align 2
|
||||
$LEFDE1:
|
||||
|
||||
#endif
|
||||
1022
src/mips/ffi.c
Normal file
1022
src/mips/ffi.c
Normal file
File diff suppressed because it is too large
Load Diff
221
src/mips/ffitarget.h
Normal file
221
src/mips/ffitarget.h
Normal file
@@ -0,0 +1,221 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for MIPS.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
#ifdef linux
|
||||
#include <asm/sgidefs.h>
|
||||
# ifndef _ABIN32
|
||||
# define _ABIN32 _MIPS_SIM_NABI32
|
||||
# endif
|
||||
# ifndef _ABI64
|
||||
# define _ABI64 _MIPS_SIM_ABI64
|
||||
# endif
|
||||
# ifndef _ABIO32
|
||||
# define _ABIO32 _MIPS_SIM_ABI32
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(_MIPS_SIM)
|
||||
-- something is very wrong --
|
||||
#else
|
||||
# if (_MIPS_SIM==_ABIN32 && defined(_ABIN32)) || (_MIPS_SIM==_ABI64 && defined(_ABI64))
|
||||
# define FFI_MIPS_N32
|
||||
# else
|
||||
# if (_MIPS_SIM==_ABIO32 && defined(_ABIO32))
|
||||
# define FFI_MIPS_O32
|
||||
# else
|
||||
-- this is an unsupported platform --
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef FFI_MIPS_O32
|
||||
/* O32 stack frames have 32bit integer args */
|
||||
# define FFI_SIZEOF_ARG 4
|
||||
#else
|
||||
/* N32 and N64 frames have 64bit integer args */
|
||||
# define FFI_SIZEOF_ARG 8
|
||||
# if _MIPS_SIM == _ABIN32
|
||||
# define FFI_SIZEOF_JAVA_RAW 4
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define FFI_FLAG_BITS 2
|
||||
|
||||
/* SGI's strange assembler requires that we multiply by 4 rather
|
||||
than shift left by FFI_FLAG_BITS */
|
||||
|
||||
#define FFI_ARGS_D FFI_TYPE_DOUBLE
|
||||
#define FFI_ARGS_F FFI_TYPE_FLOAT
|
||||
#define FFI_ARGS_DD FFI_TYPE_DOUBLE * 4 + FFI_TYPE_DOUBLE
|
||||
#define FFI_ARGS_FF FFI_TYPE_FLOAT * 4 + FFI_TYPE_FLOAT
|
||||
#define FFI_ARGS_FD FFI_TYPE_DOUBLE * 4 + FFI_TYPE_FLOAT
|
||||
#define FFI_ARGS_DF FFI_TYPE_FLOAT * 4 + FFI_TYPE_DOUBLE
|
||||
|
||||
/* Needed for N32 structure returns */
|
||||
#define FFI_TYPE_SMALLSTRUCT FFI_TYPE_UINT8
|
||||
#define FFI_TYPE_SMALLSTRUCT2 FFI_TYPE_SINT8
|
||||
|
||||
#if 0
|
||||
/* The SGI assembler can't handle this.. */
|
||||
#define FFI_TYPE_STRUCT_DD (( FFI_ARGS_DD ) << 4) + FFI_TYPE_STRUCT
|
||||
/* (and so on) */
|
||||
#else
|
||||
/* ...so we calculate these by hand! */
|
||||
#define FFI_TYPE_STRUCT_D 61
|
||||
#define FFI_TYPE_STRUCT_F 45
|
||||
#define FFI_TYPE_STRUCT_DD 253
|
||||
#define FFI_TYPE_STRUCT_FF 173
|
||||
#define FFI_TYPE_STRUCT_FD 237
|
||||
#define FFI_TYPE_STRUCT_DF 189
|
||||
#define FFI_TYPE_STRUCT_SMALL 93
|
||||
#define FFI_TYPE_STRUCT_SMALL2 109
|
||||
|
||||
/* and for n32 soft float, add 16 * 2^4 */
|
||||
#define FFI_TYPE_STRUCT_D_SOFT 317
|
||||
#define FFI_TYPE_STRUCT_F_SOFT 301
|
||||
#define FFI_TYPE_STRUCT_DD_SOFT 509
|
||||
#define FFI_TYPE_STRUCT_FF_SOFT 429
|
||||
#define FFI_TYPE_STRUCT_FD_SOFT 493
|
||||
#define FFI_TYPE_STRUCT_DF_SOFT 445
|
||||
#define FFI_TYPE_STRUCT_SOFT 16
|
||||
#endif
|
||||
|
||||
#ifdef LIBFFI_ASM
|
||||
#define v0 $2
|
||||
#define v1 $3
|
||||
#define a0 $4
|
||||
#define a1 $5
|
||||
#define a2 $6
|
||||
#define a3 $7
|
||||
#define a4 $8
|
||||
#define a5 $9
|
||||
#define a6 $10
|
||||
#define a7 $11
|
||||
#define t0 $8
|
||||
#define t1 $9
|
||||
#define t2 $10
|
||||
#define t3 $11
|
||||
#define t4 $12
|
||||
#define t5 $13
|
||||
#define t6 $14
|
||||
#define t7 $15
|
||||
#define t8 $24
|
||||
#define t9 $25
|
||||
#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
|
||||
#else /* !FFI_MIPS_O32 */
|
||||
# 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
|
||||
/* O32 stack frames have 32bit integer args */
|
||||
typedef unsigned int ffi_arg __attribute__((__mode__(__SI__)));
|
||||
typedef signed int ffi_sarg __attribute__((__mode__(__SI__)));
|
||||
#else
|
||||
/* N32 and N64 frames have 64bit integer args */
|
||||
typedef unsigned int ffi_arg __attribute__((__mode__(__DI__)));
|
||||
typedef signed int ffi_sarg __attribute__((__mode__(__DI__)));
|
||||
#endif
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_O32,
|
||||
FFI_N32,
|
||||
FFI_N64,
|
||||
FFI_O32_SOFT_FLOAT,
|
||||
FFI_N32_SOFT_FLOAT,
|
||||
FFI_N64_SOFT_FLOAT,
|
||||
|
||||
#ifdef FFI_MIPS_O32
|
||||
#ifdef __mips_soft_float
|
||||
FFI_DEFAULT_ABI = FFI_O32_SOFT_FLOAT,
|
||||
#else
|
||||
FFI_DEFAULT_ABI = FFI_O32,
|
||||
#endif
|
||||
#else
|
||||
# if _MIPS_SIM==_ABI64
|
||||
# ifdef __mips_soft_float
|
||||
FFI_DEFAULT_ABI = FFI_N64_SOFT_FLOAT,
|
||||
# else
|
||||
FFI_DEFAULT_ABI = FFI_N64,
|
||||
# endif
|
||||
# else
|
||||
# ifdef __mips_soft_float
|
||||
FFI_DEFAULT_ABI = FFI_N32_SOFT_FLOAT,
|
||||
# else
|
||||
FFI_DEFAULT_ABI = FFI_N32,
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
|
||||
#define FFI_EXTRA_CIF_FIELDS unsigned rstruct_flag
|
||||
#endif /* !LIBFFI_ASM */
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#if defined(FFI_MIPS_O32)
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 20
|
||||
#else
|
||||
/* 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
|
||||
|
||||
#endif
|
||||
|
||||
587
src/mips/n32.S
Normal file
587
src/mips/n32.S
Normal file
@@ -0,0 +1,587 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
n32.S - Copyright (c) 1996, 1998, 2005 Red Hat, Inc.
|
||||
|
||||
MIPS 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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
/* Only build this code if we are compiling for n32 */
|
||||
|
||||
#if defined(FFI_MIPS_N32)
|
||||
|
||||
#define callback a0
|
||||
#define bytes a2
|
||||
#define flags a3
|
||||
#define raddr a4
|
||||
#define fn a5
|
||||
|
||||
#define SIZEOF_FRAME ( 8 * FFI_SIZEOF_ARG )
|
||||
|
||||
.abicalls
|
||||
.text
|
||||
.align 2
|
||||
.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
|
||||
REG_S raddr, 4*FFI_SIZEOF_ARG($fp) # raddr
|
||||
REG_S fn, 5*FFI_SIZEOF_ARG($fp) # fn
|
||||
|
||||
# Allocate at least 4 words in the argstack
|
||||
move v0, bytes
|
||||
bge bytes, 4 * FFI_SIZEOF_ARG, bigger
|
||||
LI v0, 4 * FFI_SIZEOF_ARG
|
||||
b sixteen
|
||||
|
||||
bigger:
|
||||
ADDU t4, v0, 2 * FFI_SIZEOF_ARG -1 # make sure it is aligned
|
||||
and v0, t4, -2 * FFI_SIZEOF_ARG # to a proper boundry.
|
||||
|
||||
sixteen:
|
||||
SUBU $sp, $sp, v0 # move the stack pointer to reflect the
|
||||
# arg space
|
||||
|
||||
move a0, $sp # 4 * FFI_SIZEOF_ARG
|
||||
ADDU a3, $fp, 3 * FFI_SIZEOF_ARG
|
||||
|
||||
# Call ffi_prep_args
|
||||
jal t9
|
||||
|
||||
# Copy the stack pointer to t9
|
||||
move t9, $sp
|
||||
|
||||
# Fix the stack if there are more than 8 64bit slots worth
|
||||
# of arguments.
|
||||
|
||||
# Load the number of bytes
|
||||
REG_L t6, 2*FFI_SIZEOF_ARG($fp)
|
||||
|
||||
# Is it bigger than 8 * FFI_SIZEOF_ARG?
|
||||
daddiu t8, t6, -(8 * FFI_SIZEOF_ARG)
|
||||
bltz t8, loadregs
|
||||
|
||||
ADDU t9, t9, t8
|
||||
|
||||
loadregs:
|
||||
|
||||
REG_L t6, 3*FFI_SIZEOF_ARG($fp) # load the flags word into t6.
|
||||
|
||||
and t4, t6, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg1_floatp
|
||||
REG_L a0, 0*FFI_SIZEOF_ARG(t9)
|
||||
b arg1_next
|
||||
arg1_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg1_doublep
|
||||
l.s $f12, 0*FFI_SIZEOF_ARG(t9)
|
||||
b arg1_next
|
||||
arg1_doublep:
|
||||
l.d $f12, 0*FFI_SIZEOF_ARG(t9)
|
||||
arg1_next:
|
||||
|
||||
SRL t4, t6, 1*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg2_floatp
|
||||
REG_L a1, 1*FFI_SIZEOF_ARG(t9)
|
||||
b arg2_next
|
||||
arg2_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg2_doublep
|
||||
l.s $f13, 1*FFI_SIZEOF_ARG(t9)
|
||||
b arg2_next
|
||||
arg2_doublep:
|
||||
l.d $f13, 1*FFI_SIZEOF_ARG(t9)
|
||||
arg2_next:
|
||||
|
||||
SRL t4, t6, 2*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg3_floatp
|
||||
REG_L a2, 2*FFI_SIZEOF_ARG(t9)
|
||||
b arg3_next
|
||||
arg3_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg3_doublep
|
||||
l.s $f14, 2*FFI_SIZEOF_ARG(t9)
|
||||
b arg3_next
|
||||
arg3_doublep:
|
||||
l.d $f14, 2*FFI_SIZEOF_ARG(t9)
|
||||
arg3_next:
|
||||
|
||||
SRL t4, t6, 3*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg4_floatp
|
||||
REG_L a3, 3*FFI_SIZEOF_ARG(t9)
|
||||
b arg4_next
|
||||
arg4_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg4_doublep
|
||||
l.s $f15, 3*FFI_SIZEOF_ARG(t9)
|
||||
b arg4_next
|
||||
arg4_doublep:
|
||||
l.d $f15, 3*FFI_SIZEOF_ARG(t9)
|
||||
arg4_next:
|
||||
|
||||
SRL t4, t6, 4*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg5_floatp
|
||||
REG_L a4, 4*FFI_SIZEOF_ARG(t9)
|
||||
b arg5_next
|
||||
arg5_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg5_doublep
|
||||
l.s $f16, 4*FFI_SIZEOF_ARG(t9)
|
||||
b arg5_next
|
||||
arg5_doublep:
|
||||
l.d $f16, 4*FFI_SIZEOF_ARG(t9)
|
||||
arg5_next:
|
||||
|
||||
SRL t4, t6, 5*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg6_floatp
|
||||
REG_L a5, 5*FFI_SIZEOF_ARG(t9)
|
||||
b arg6_next
|
||||
arg6_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg6_doublep
|
||||
l.s $f17, 5*FFI_SIZEOF_ARG(t9)
|
||||
b arg6_next
|
||||
arg6_doublep:
|
||||
l.d $f17, 5*FFI_SIZEOF_ARG(t9)
|
||||
arg6_next:
|
||||
|
||||
SRL t4, t6, 6*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg7_floatp
|
||||
REG_L a6, 6*FFI_SIZEOF_ARG(t9)
|
||||
b arg7_next
|
||||
arg7_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg7_doublep
|
||||
l.s $f18, 6*FFI_SIZEOF_ARG(t9)
|
||||
b arg7_next
|
||||
arg7_doublep:
|
||||
l.d $f18, 6*FFI_SIZEOF_ARG(t9)
|
||||
arg7_next:
|
||||
|
||||
SRL t4, t6, 7*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg8_floatp
|
||||
REG_L a7, 7*FFI_SIZEOF_ARG(t9)
|
||||
b arg8_next
|
||||
arg8_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg8_doublep
|
||||
l.s $f19, 7*FFI_SIZEOF_ARG(t9)
|
||||
b arg8_next
|
||||
arg8_doublep:
|
||||
l.d $f19, 7*FFI_SIZEOF_ARG(t9)
|
||||
arg8_next:
|
||||
|
||||
callit:
|
||||
# Load the function pointer
|
||||
REG_L t9, 5*FFI_SIZEOF_ARG($fp)
|
||||
|
||||
# If the return value pointer is NULL, assume no return value.
|
||||
REG_L t5, 4*FFI_SIZEOF_ARG($fp)
|
||||
beqz t5, noretval
|
||||
|
||||
# Shift the return type flag over
|
||||
SRL t6, 8*FFI_FLAG_BITS
|
||||
|
||||
beq t6, FFI_TYPE_SINT32, retint
|
||||
bne t6, FFI_TYPE_INT, retfloat
|
||||
retint:
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
REG_S v0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retfloat:
|
||||
bne t6, FFI_TYPE_FLOAT, retdouble
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.s $f0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retdouble:
|
||||
bne t6, FFI_TYPE_DOUBLE, retstruct_d
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.d $f0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_d:
|
||||
bne t6, FFI_TYPE_STRUCT_D, retstruct_f
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.d $f0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_f:
|
||||
bne t6, FFI_TYPE_STRUCT_F, retstruct_d_d
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.s $f0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_d_d:
|
||||
bne t6, FFI_TYPE_STRUCT_DD, retstruct_f_f
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.d $f0, 0(t4)
|
||||
s.d $f2, 8(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_f_f:
|
||||
bne t6, FFI_TYPE_STRUCT_FF, retstruct_d_f
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.s $f0, 0(t4)
|
||||
s.s $f2, 4(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_d_f:
|
||||
bne t6, FFI_TYPE_STRUCT_DF, retstruct_f_d
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.d $f0, 0(t4)
|
||||
s.s $f2, 8(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_f_d:
|
||||
bne t6, FFI_TYPE_STRUCT_FD, retstruct_d_soft
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.s $f0, 0(t4)
|
||||
s.d $f2, 8(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_d_soft:
|
||||
bne t6, FFI_TYPE_STRUCT_D_SOFT, retstruct_f_soft
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
sd v0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_f_soft:
|
||||
bne t6, FFI_TYPE_STRUCT_F_SOFT, retstruct_d_d_soft
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
sw v0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_d_d_soft:
|
||||
bne t6, FFI_TYPE_STRUCT_DD_SOFT, retstruct_f_f_soft
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
sd v0, 0(t4)
|
||||
sd v1, 8(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_f_f_soft:
|
||||
bne t6, FFI_TYPE_STRUCT_FF_SOFT, retstruct_d_f_soft
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
sw v0, 0(t4)
|
||||
sw v1, 4(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_d_f_soft:
|
||||
bne t6, FFI_TYPE_STRUCT_DF_SOFT, retstruct_f_d_soft
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
sd v0, 0(t4)
|
||||
sw v1, 8(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_f_d_soft:
|
||||
bne t6, FFI_TYPE_STRUCT_FD_SOFT, retstruct_small
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
sw v0, 0(t4)
|
||||
sd v1, 8(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_small:
|
||||
bne t6, FFI_TYPE_STRUCT_SMALL, retstruct_small2
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
REG_S v0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_small2:
|
||||
bne t6, FFI_TYPE_STRUCT_SMALL2, retstruct
|
||||
jal t9
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
REG_S v0, 0(t4)
|
||||
REG_S v1, 8(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct:
|
||||
noretval:
|
||||
jal t9
|
||||
|
||||
# Epilogue
|
||||
epilogue:
|
||||
move $sp, $fp
|
||||
REG_L $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Restore frame pointer
|
||||
REG_L ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp) # Restore return address
|
||||
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_SINT32, cls_retint
|
||||
lw v0, V0_OFF2($sp)
|
||||
b cls_epilogue
|
||||
|
||||
cls_retint:
|
||||
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
|
||||
381
src/mips/o32.S
Normal file
381
src/mips/o32.S
Normal file
@@ -0,0 +1,381 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
o32.S - Copyright (c) 1996, 1998, 2005 Red Hat, Inc.
|
||||
|
||||
MIPS 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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
/* Only build this code if we are compiling for o32 */
|
||||
|
||||
#if defined(FFI_MIPS_O32)
|
||||
|
||||
#define callback a0
|
||||
#define bytes a2
|
||||
#define flags a3
|
||||
|
||||
#define SIZEOF_FRAME (4 * FFI_SIZEOF_ARG + 2 * FFI_SIZEOF_ARG)
|
||||
#define A3_OFF (SIZEOF_FRAME + 3 * FFI_SIZEOF_ARG)
|
||||
#define FP_OFF (SIZEOF_FRAME - 2 * FFI_SIZEOF_ARG)
|
||||
#define RA_OFF (SIZEOF_FRAME - 1 * FFI_SIZEOF_ARG)
|
||||
|
||||
.abicalls
|
||||
.text
|
||||
.align 2
|
||||
.globl ffi_call_O32
|
||||
.ent ffi_call_O32
|
||||
ffi_call_O32:
|
||||
$LFB0:
|
||||
# Prologue
|
||||
SUBU $sp, SIZEOF_FRAME # Frame size
|
||||
$LCFI0:
|
||||
REG_S $fp, FP_OFF($sp) # Save frame pointer
|
||||
$LCFI1:
|
||||
REG_S ra, RA_OFF($sp) # Save return address
|
||||
$LCFI2:
|
||||
move $fp, $sp
|
||||
|
||||
$LCFI3:
|
||||
move t9, callback # callback function pointer
|
||||
REG_S flags, A3_OFF($fp) # flags
|
||||
|
||||
# Allocate at least 4 words in the argstack
|
||||
LI v0, 4 * FFI_SIZEOF_ARG
|
||||
blt bytes, v0, sixteen
|
||||
|
||||
ADDU v0, bytes, 7 # make sure it is aligned
|
||||
and v0, -8 # to an 8 byte boundry
|
||||
|
||||
sixteen:
|
||||
SUBU $sp, v0 # move the stack pointer to reflect the
|
||||
# arg space
|
||||
|
||||
ADDU a0, $sp, 4 * FFI_SIZEOF_ARG
|
||||
|
||||
jalr t9
|
||||
|
||||
REG_L t0, A3_OFF($fp) # load the flags word
|
||||
SRL t2, t0, 4 # shift our arg info
|
||||
and t0, ((1<<4)-1) # mask out the return type
|
||||
|
||||
ADDU $sp, 4 * FFI_SIZEOF_ARG # adjust $sp to new args
|
||||
|
||||
bnez t0, pass_d # make it quick for int
|
||||
REG_L a0, 0*FFI_SIZEOF_ARG($sp) # just go ahead and load the
|
||||
REG_L a1, 1*FFI_SIZEOF_ARG($sp) # four regs.
|
||||
REG_L a2, 2*FFI_SIZEOF_ARG($sp)
|
||||
REG_L a3, 3*FFI_SIZEOF_ARG($sp)
|
||||
b call_it
|
||||
|
||||
pass_d:
|
||||
bne t0, FFI_ARGS_D, pass_f
|
||||
l.d $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args
|
||||
REG_L a2, 2*FFI_SIZEOF_ARG($sp) # passing a double
|
||||
REG_L a3, 3*FFI_SIZEOF_ARG($sp)
|
||||
b call_it
|
||||
|
||||
pass_f:
|
||||
bne t0, FFI_ARGS_F, pass_d_d
|
||||
l.s $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args
|
||||
REG_L a1, 1*FFI_SIZEOF_ARG($sp) # passing a float
|
||||
REG_L a2, 2*FFI_SIZEOF_ARG($sp)
|
||||
REG_L a3, 3*FFI_SIZEOF_ARG($sp)
|
||||
b call_it
|
||||
|
||||
pass_d_d:
|
||||
bne t0, FFI_ARGS_DD, pass_f_f
|
||||
l.d $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args
|
||||
l.d $f14, 2*FFI_SIZEOF_ARG($sp) # passing two doubles
|
||||
b call_it
|
||||
|
||||
pass_f_f:
|
||||
bne t0, FFI_ARGS_FF, pass_d_f
|
||||
l.s $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args
|
||||
l.s $f14, 1*FFI_SIZEOF_ARG($sp) # passing two floats
|
||||
REG_L a2, 2*FFI_SIZEOF_ARG($sp)
|
||||
REG_L a3, 3*FFI_SIZEOF_ARG($sp)
|
||||
b call_it
|
||||
|
||||
pass_d_f:
|
||||
bne t0, FFI_ARGS_DF, pass_f_d
|
||||
l.d $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args
|
||||
l.s $f14, 2*FFI_SIZEOF_ARG($sp) # passing double and float
|
||||
REG_L a3, 3*FFI_SIZEOF_ARG($sp)
|
||||
b call_it
|
||||
|
||||
pass_f_d:
|
||||
# assume that the only other combination must be float then double
|
||||
# bne t0, FFI_ARGS_F_D, call_it
|
||||
l.s $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args
|
||||
l.d $f14, 2*FFI_SIZEOF_ARG($sp) # passing double and float
|
||||
|
||||
call_it:
|
||||
# Load the function pointer
|
||||
REG_L t9, SIZEOF_FRAME + 5*FFI_SIZEOF_ARG($fp)
|
||||
|
||||
# If the return value pointer is NULL, assume no return value.
|
||||
REG_L t1, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
|
||||
beqz t1, noretval
|
||||
|
||||
bne t2, FFI_TYPE_INT, retlonglong
|
||||
jalr t9
|
||||
REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
|
||||
REG_S v0, 0(t0)
|
||||
b epilogue
|
||||
|
||||
retlonglong:
|
||||
# Really any 64-bit int, signed or not.
|
||||
bne t2, FFI_TYPE_UINT64, retfloat
|
||||
jalr t9
|
||||
REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
|
||||
REG_S v1, 4(t0)
|
||||
REG_S v0, 0(t0)
|
||||
b epilogue
|
||||
|
||||
retfloat:
|
||||
bne t2, FFI_TYPE_FLOAT, retdouble
|
||||
jalr t9
|
||||
REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
|
||||
s.s $f0, 0(t0)
|
||||
b epilogue
|
||||
|
||||
retdouble:
|
||||
bne t2, FFI_TYPE_DOUBLE, noretval
|
||||
jalr t9
|
||||
REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
|
||||
s.d $f0, 0(t0)
|
||||
b epilogue
|
||||
|
||||
noretval:
|
||||
jalr t9
|
||||
|
||||
# Epilogue
|
||||
epilogue:
|
||||
move $sp, $fp
|
||||
REG_L $fp, FP_OFF($sp) # Restore frame pointer
|
||||
REG_L ra, RA_OFF($sp) # Restore return address
|
||||
ADDU $sp, SIZEOF_FRAME # Fix stack pointer
|
||||
j ra
|
||||
|
||||
$LFE0:
|
||||
.end ffi_call_O32
|
||||
|
||||
|
||||
/* ffi_closure_O32. Expects address of the passed-in ffi_closure
|
||||
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:
|
||||
|
||||
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)
|
||||
#define A3_OFF2 (SIZEOF_FRAME2 + 3 * FFI_SIZEOF_ARG)
|
||||
#define A2_OFF2 (SIZEOF_FRAME2 + 2 * FFI_SIZEOF_ARG)
|
||||
#define A1_OFF2 (SIZEOF_FRAME2 + 1 * FFI_SIZEOF_ARG)
|
||||
#define A0_OFF2 (SIZEOF_FRAME2 + 0 * FFI_SIZEOF_ARG)
|
||||
#define RA_OFF2 (SIZEOF_FRAME2 - 1 * FFI_SIZEOF_ARG)
|
||||
#define FP_OFF2 (SIZEOF_FRAME2 - 2 * FFI_SIZEOF_ARG)
|
||||
#define S0_OFF2 (SIZEOF_FRAME2 - 3 * FFI_SIZEOF_ARG)
|
||||
#define GP_OFF2 (SIZEOF_FRAME2 - 4 * FFI_SIZEOF_ARG)
|
||||
#define V1_OFF2 (SIZEOF_FRAME2 - 5 * FFI_SIZEOF_ARG)
|
||||
#define V0_OFF2 (SIZEOF_FRAME2 - 6 * FFI_SIZEOF_ARG)
|
||||
#define FA_1_1_OFF2 (SIZEOF_FRAME2 - 7 * FFI_SIZEOF_ARG)
|
||||
#define FA_1_0_OFF2 (SIZEOF_FRAME2 - 8 * FFI_SIZEOF_ARG)
|
||||
#define FA_0_1_OFF2 (SIZEOF_FRAME2 - 9 * FFI_SIZEOF_ARG)
|
||||
#define FA_0_0_OFF2 (SIZEOF_FRAME2 - 10 * FFI_SIZEOF_ARG)
|
||||
|
||||
.text
|
||||
.align 2
|
||||
.globl ffi_closure_O32
|
||||
.ent ffi_closure_O32
|
||||
ffi_closure_O32:
|
||||
$LFB1:
|
||||
# Prologue
|
||||
.frame $fp, SIZEOF_FRAME2, ra
|
||||
.set noreorder
|
||||
.cpload t9
|
||||
.set reorder
|
||||
SUBU $sp, SIZEOF_FRAME2
|
||||
.cprestore GP_OFF2
|
||||
$LCFI4:
|
||||
REG_S $16, S0_OFF2($sp) # Save s0
|
||||
REG_S $fp, FP_OFF2($sp) # Save frame pointer
|
||||
REG_S ra, RA_OFF2($sp) # Save return address
|
||||
$LCFI6:
|
||||
move $fp, $sp
|
||||
|
||||
$LCFI7:
|
||||
# Store all possible argument registers. If there are more than
|
||||
# four arguments, then they are stored above where we put a3.
|
||||
REG_S a0, A0_OFF2($fp)
|
||||
REG_S a1, A1_OFF2($fp)
|
||||
REG_S a2, A2_OFF2($fp)
|
||||
REG_S a3, A3_OFF2($fp)
|
||||
|
||||
# Load ABI enum to s0
|
||||
REG_L $16, 20($12) # cif pointer follows tramp.
|
||||
REG_L $16, 0($16) # abi is first member.
|
||||
|
||||
li $13, 1 # FFI_O32
|
||||
bne $16, $13, 1f # Skip fp save if FFI_O32_SOFT_FLOAT
|
||||
|
||||
# Store all possible float/double registers.
|
||||
s.d $f12, FA_0_0_OFF2($fp)
|
||||
s.d $f14, FA_1_0_OFF2($fp)
|
||||
1:
|
||||
# Call ffi_closure_mips_inner_O32 to do the work.
|
||||
la t9, ffi_closure_mips_inner_O32
|
||||
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
|
||||
jalr t9
|
||||
|
||||
# Load the return value into the appropriate register.
|
||||
move $8, $2
|
||||
li $9, FFI_TYPE_VOID
|
||||
beq $8, $9, closure_done
|
||||
|
||||
li $13, 1 # FFI_O32
|
||||
bne $16, $13, 1f # Skip fp restore if FFI_O32_SOFT_FLOAT
|
||||
|
||||
li $9, FFI_TYPE_FLOAT
|
||||
l.s $f0, V0_OFF2($fp)
|
||||
beq $8, $9, closure_done
|
||||
|
||||
li $9, FFI_TYPE_DOUBLE
|
||||
l.d $f0, V0_OFF2($fp)
|
||||
beq $8, $9, closure_done
|
||||
1:
|
||||
REG_L $3, V1_OFF2($fp)
|
||||
REG_L $2, V0_OFF2($fp)
|
||||
|
||||
closure_done:
|
||||
# Epilogue
|
||||
move $sp, $fp
|
||||
REG_L $16, S0_OFF2($sp) # Restore s0
|
||||
REG_L $fp, FP_OFF2($sp) # Restore frame pointer
|
||||
REG_L ra, RA_OFF2($sp) # Restore return address
|
||||
ADDU $sp, SIZEOF_FRAME2
|
||||
j ra
|
||||
$LFE1:
|
||||
.end ffi_closure_O32
|
||||
|
||||
/* DWARF-2 unwind info. */
|
||||
|
||||
.section .eh_frame,"a",@progbits
|
||||
$Lframe0:
|
||||
.4byte $LECIE0-$LSCIE0 # Length of Common Information Entry
|
||||
$LSCIE0:
|
||||
.4byte 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.uleb128 0x1 # CIE Code Alignment Factor
|
||||
.sleb128 4 # CIE Data Alignment Factor
|
||||
.byte 0x1f # CIE RA Column
|
||||
.uleb128 0x1 # Augmentation size
|
||||
.byte 0x00 # FDE Encoding (absptr)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1d
|
||||
.uleb128 0x0
|
||||
.align 2
|
||||
$LECIE0:
|
||||
$LSFDE0:
|
||||
.4byte $LEFDE0-$LASFDE0 # FDE Length
|
||||
$LASFDE0:
|
||||
.4byte $LASFDE0-$Lframe0 # FDE CIE offset
|
||||
.4byte $LFB0 # FDE initial location
|
||||
.4byte $LFE0-$LFB0 # FDE address range
|
||||
.uleb128 0x0 # Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI0-$LFB0
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 0x18
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI2-$LCFI0
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x1e # $fp
|
||||
.sleb128 -2 # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp)
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x1f # $ra
|
||||
.sleb128 -1 # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp)
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI3-$LCFI2
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1e
|
||||
.uleb128 0x18
|
||||
.align 2
|
||||
$LEFDE0:
|
||||
$LSFDE1:
|
||||
.4byte $LEFDE1-$LASFDE1 # FDE Length
|
||||
$LASFDE1:
|
||||
.4byte $LASFDE1-$Lframe0 # FDE CIE offset
|
||||
.4byte $LFB1 # FDE initial location
|
||||
.4byte $LFE1-$LFB1 # FDE address range
|
||||
.uleb128 0x0 # Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI4-$LFB1
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 0x38
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI6-$LCFI4
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x10 # $16
|
||||
.sleb128 -3 # SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp)
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x1e # $fp
|
||||
.sleb128 -2 # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp)
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x1f # $ra
|
||||
.sleb128 -1 # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp)
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI7-$LCFI6
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1e
|
||||
.uleb128 0x38
|
||||
.align 2
|
||||
$LEFDE1:
|
||||
|
||||
#endif
|
||||
128
src/moxie/eabi.S
Normal file
128
src/moxie/eabi.S
Normal file
@@ -0,0 +1,128 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
eabi.S - Copyright (c) 2004 Anthony Green
|
||||
|
||||
FR-V 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
.globl ffi_prep_args_EABI
|
||||
|
||||
.text
|
||||
.p2align 4
|
||||
.globl ffi_call_EABI
|
||||
.type ffi_call_EABI, @function
|
||||
|
||||
# gr8 : ffi_prep_args
|
||||
# gr9 : &ecif
|
||||
# gr10: cif->bytes
|
||||
# gr11: fig->flags
|
||||
# gr12: ecif.rvalue
|
||||
# gr13: fn
|
||||
|
||||
ffi_call_EABI:
|
||||
addi sp, #-80, sp
|
||||
sti fp, @(sp, #24)
|
||||
addi sp, #24, fp
|
||||
movsg lr, gr5
|
||||
|
||||
/* Make room for the new arguments. */
|
||||
/* subi sp, fp, gr10 */
|
||||
|
||||
/* Store return address and incoming args on stack. */
|
||||
sti gr5, @(fp, #8)
|
||||
sti gr8, @(fp, #-4)
|
||||
sti gr9, @(fp, #-8)
|
||||
sti gr10, @(fp, #-12)
|
||||
sti gr11, @(fp, #-16)
|
||||
sti gr12, @(fp, #-20)
|
||||
sti gr13, @(fp, #-24)
|
||||
|
||||
sub sp, gr10, sp
|
||||
|
||||
/* Call ffi_prep_args. */
|
||||
ldi @(fp, #-4), gr4
|
||||
addi sp, #0, gr8
|
||||
ldi @(fp, #-8), gr9
|
||||
#ifdef __FRV_FDPIC__
|
||||
ldd @(gr4, gr0), gr14
|
||||
calll @(gr14, gr0)
|
||||
#else
|
||||
calll @(gr4, gr0)
|
||||
#endif
|
||||
|
||||
/* ffi_prep_args returns the new stack pointer. */
|
||||
mov gr8, gr4
|
||||
|
||||
ldi @(sp, #0), gr8
|
||||
ldi @(sp, #4), gr9
|
||||
ldi @(sp, #8), gr10
|
||||
ldi @(sp, #12), gr11
|
||||
ldi @(sp, #16), gr12
|
||||
ldi @(sp, #20), gr13
|
||||
|
||||
/* Always copy the return value pointer into the hidden
|
||||
parameter register. This is only strictly necessary
|
||||
when we're returning an aggregate type, but it doesn't
|
||||
hurt to do this all the time, and it saves a branch. */
|
||||
ldi @(fp, #-20), gr3
|
||||
|
||||
/* Use the ffi_prep_args return value for the new sp. */
|
||||
mov gr4, sp
|
||||
|
||||
/* Call the target function. */
|
||||
ldi @(fp, -24), gr4
|
||||
#ifdef __FRV_FDPIC__
|
||||
ldd @(gr4, gr0), gr14
|
||||
calll @(gr14, gr0)
|
||||
#else
|
||||
calll @(gr4, gr0)
|
||||
#endif
|
||||
|
||||
/* Store the result. */
|
||||
ldi @(fp, #-16), gr10 /* fig->flags */
|
||||
ldi @(fp, #-20), gr4 /* ecif.rvalue */
|
||||
|
||||
/* Is the return value stored in two registers? */
|
||||
cmpi gr10, #8, icc0
|
||||
bne icc0, 0, .L2
|
||||
/* Yes, save them. */
|
||||
sti gr8, @(gr4, #0)
|
||||
sti gr9, @(gr4, #4)
|
||||
bra .L3
|
||||
.L2:
|
||||
/* Is the return value a structure? */
|
||||
cmpi gr10, #-1, icc0
|
||||
beq icc0, 0, .L3
|
||||
/* No, save a 4 byte return value. */
|
||||
sti gr8, @(gr4, #0)
|
||||
.L3:
|
||||
|
||||
/* Restore the stack, and return. */
|
||||
ldi @(fp, 8), gr5
|
||||
ld @(fp, gr0), fp
|
||||
addi sp,#80,sp
|
||||
jmpl @(gr5,gr0)
|
||||
.size ffi_call_EABI, .-ffi_call_EABI
|
||||
|
||||
276
src/moxie/ffi.c
Normal file
276
src/moxie/ffi.c
Normal file
@@ -0,0 +1,276 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (C) 2009 Anthony Green
|
||||
|
||||
Moxie 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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* 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)
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
register int count = 0;
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
argp = stack;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
(i != 0);
|
||||
i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
z = (*p_arg)->size;
|
||||
|
||||
if ((*p_arg)->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
z = sizeof(void*);
|
||||
*(void **) argp = *p_argv;
|
||||
}
|
||||
/* if ((*p_arg)->type == FFI_TYPE_FLOAT)
|
||||
{
|
||||
if (count > 24)
|
||||
{
|
||||
// This is going on the stack. Turn it into a double.
|
||||
*(double *) argp = (double) *(float*)(* p_argv);
|
||||
z = sizeof(double);
|
||||
}
|
||||
else
|
||||
*(void **) argp = *(void **)(* p_argv);
|
||||
} */
|
||||
else if (z < sizeof(int))
|
||||
{
|
||||
z = sizeof(int);
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
}
|
||||
else if (z == sizeof(int))
|
||||
{
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(argp, *p_argv, z);
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
count += z;
|
||||
}
|
||||
|
||||
return (stack + ((count > 24) ? 24 : ALIGN_DOWN(count, 8)));
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
cif->flags = -1;
|
||||
else
|
||||
cif->flags = cif->rtype->size;
|
||||
|
||||
cif->bytes = ALIGN (cif->bytes, 8);
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern void ffi_call_EABI(void *(*)(char *, extended_cif *),
|
||||
extended_cif *,
|
||||
unsigned, unsigned,
|
||||
unsigned *,
|
||||
void (*fn)(void));
|
||||
|
||||
void ffi_call(ffi_cif *cif,
|
||||
void (*fn)(void),
|
||||
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_EABI:
|
||||
ffi_call_EABI(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
|
||||
unsigned arg4, unsigned arg5, unsigned arg6)
|
||||
{
|
||||
/* This function is called by a trampoline. The trampoline stows a
|
||||
pointer to the ffi_closure object in gr7. We must save this
|
||||
pointer in a place that will persist while we do our work. */
|
||||
register ffi_closure *creg __asm__ ("gr7");
|
||||
ffi_closure *closure = creg;
|
||||
|
||||
/* Arguments that don't fit in registers are found on the stack
|
||||
at a fixed offset above the current frame pointer. */
|
||||
register char *frame_pointer __asm__ ("fp");
|
||||
char *stack_args = frame_pointer + 16;
|
||||
|
||||
/* Lay the register arguments down in a continuous chunk of memory. */
|
||||
unsigned register_args[6] =
|
||||
{ arg1, arg2, arg3, arg4, arg5, arg6 };
|
||||
|
||||
ffi_cif *cif = closure->cif;
|
||||
ffi_type **arg_types = cif->arg_types;
|
||||
void **avalue = alloca (cif->nargs * sizeof(void *));
|
||||
char *ptr = (char *) register_args;
|
||||
int i;
|
||||
|
||||
/* Find the address of each argument. */
|
||||
for (i = 0; i < cif->nargs; i++)
|
||||
{
|
||||
switch (arg_types[i]->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT8:
|
||||
avalue[i] = ptr + 3;
|
||||
break;
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
avalue[i] = ptr + 2;
|
||||
break;
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_FLOAT:
|
||||
avalue[i] = ptr;
|
||||
break;
|
||||
case FFI_TYPE_STRUCT:
|
||||
avalue[i] = *(void**)ptr;
|
||||
break;
|
||||
default:
|
||||
/* This is an 8-byte value. */
|
||||
avalue[i] = ptr;
|
||||
ptr += 4;
|
||||
break;
|
||||
}
|
||||
ptr += 4;
|
||||
|
||||
/* If we've handled more arguments than fit in registers,
|
||||
start looking at the those passed on the stack. */
|
||||
if (ptr == ((char *)register_args + (6*4)))
|
||||
ptr = stack_args;
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
/* The caller allocates space for the return structure, and
|
||||
passes a pointer to this space in gr3. Use this value directly
|
||||
as the return value. */
|
||||
register void *return_struct_ptr __asm__("gr3");
|
||||
(closure->fun) (cif, return_struct_ptr, avalue, closure->user_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocate space for the return value and call the function. */
|
||||
long long rvalue;
|
||||
(closure->fun) (cif, &rvalue, avalue, closure->user_data);
|
||||
|
||||
/* Functions return 4-byte or smaller results in gr8. 8-byte
|
||||
values also use gr9. We fill the both, even for small return
|
||||
values, just to avoid a branch. */
|
||||
asm ("ldi @(%0, #0), gr8" : : "r" (&rvalue));
|
||||
asm ("ldi @(%0, #0), gr9" : : "r" (&((int *) &rvalue)[1]));
|
||||
}
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
unsigned int *tramp = (unsigned int *) &closure->tramp[0];
|
||||
unsigned long fn = (long) ffi_closure_eabi;
|
||||
unsigned long cls = (long) codeloc;
|
||||
int i;
|
||||
|
||||
fn = (unsigned long) ffi_closure_eabi;
|
||||
|
||||
tramp[0] = 0x8cfc0000 + (fn & 0xffff); /* setlos lo(fn), gr6 */
|
||||
tramp[1] = 0x8efc0000 + (cls & 0xffff); /* setlos lo(cls), gr7 */
|
||||
tramp[2] = 0x8cf80000 + (fn >> 16); /* sethi hi(fn), gr6 */
|
||||
tramp[3] = 0x8ef80000 + (cls >> 16); /* sethi hi(cls), gr7 */
|
||||
tramp[4] = 0x80300006; /* jmpl @(gr0, gr6) */
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
/* Cache flushing. */
|
||||
for (i = 0; i < FFI_TRAMPOLINE_SIZE; i++)
|
||||
__asm__ volatile ("dcf @(%0,%1)\n\tici @(%2,%1)" :: "r" (tramp), "r" (i),
|
||||
"r" (codeloc));
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
56
src/moxie/ffitarget.h
Normal file
56
src/moxie/ffitarget.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 2009 Anthony Green
|
||||
Target configuration macros for Moxie
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
/* ---- System specific configurations ----------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
|
||||
#ifdef MOXIE
|
||||
FFI_EABI,
|
||||
FFI_DEFAULT_ABI = FFI_EABI,
|
||||
#endif
|
||||
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 0
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
/* Trampolines are 5 4-byte instructions long. */
|
||||
#define FFI_TRAMPOLINE_SIZE (5*4)
|
||||
|
||||
#endif
|
||||
164
src/pa/.svn/entries
Normal file
164
src/pa/.svn/entries
Normal file
@@ -0,0 +1,164 @@
|
||||
10
|
||||
|
||||
dir
|
||||
152280
|
||||
svn://gcc.gnu.org/svn/gcc/trunk/libffi/src/pa
|
||||
svn://gcc.gnu.org/svn/gcc
|
||||
|
||||
|
||||
|
||||
2009-06-04T15:43:03.499507Z
|
||||
148172
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
138bc75d-0d04-0410-961f-82ee72b054a4
|
||||
|
||||
linux.S
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:02.000000Z
|
||||
a0da8c57c7ff9de674c6728fe321f0be
|
||||
2009-06-04T15:43:03.499507Z
|
||||
148172
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
9187
|
||||
|
||||
ffitarget.h
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:02.000000Z
|
||||
3a6fbb541af62fcd2ae81d874b0c4487
|
||||
2009-06-04T15:11:12.475454Z
|
||||
148171
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
2375
|
||||
|
||||
ffi.c
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:02.000000Z
|
||||
7584ecb991cb652c6935e9f0069dfda3
|
||||
2009-06-04T15:43:03.499507Z
|
||||
148172
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
19820
|
||||
|
||||
hpux32.S
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:02.000000Z
|
||||
f3279dc3ee2648b08c274f2457d17660
|
||||
2009-06-04T15:43:03.499507Z
|
||||
148172
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
9226
|
||||
|
||||
709
src/pa/.svn/text-base/ffi.c.svn-base
Normal file
709
src/pa/.svn/text-base/ffi.c.svn-base
Normal file
@@ -0,0 +1,709 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - (c) 2003-2004 Randolph Chung <tausq@debian.org>
|
||||
(c) 2008 Red Hat, Inc.
|
||||
|
||||
HPPA Foreign Function Interface
|
||||
HP-UX PA ABI support (c) 2006 Free Software Foundation, Inc.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define ROUND_UP(v, a) (((size_t)(v) + (a) - 1) & ~((a) - 1))
|
||||
|
||||
#define MIN_STACK_SIZE 64
|
||||
#define FIRST_ARG_SLOT 9
|
||||
#define DEBUG_LEVEL 0
|
||||
|
||||
#define fldw(addr, fpreg) \
|
||||
__asm__ volatile ("fldw 0(%0), %%" #fpreg "L" : : "r"(addr) : #fpreg)
|
||||
#define fstw(fpreg, addr) \
|
||||
__asm__ volatile ("fstw %%" #fpreg "L, 0(%0)" : : "r"(addr))
|
||||
#define fldd(addr, fpreg) \
|
||||
__asm__ volatile ("fldd 0(%0), %%" #fpreg : : "r"(addr) : #fpreg)
|
||||
#define fstd(fpreg, addr) \
|
||||
__asm__ volatile ("fstd %%" #fpreg "L, 0(%0)" : : "r"(addr))
|
||||
|
||||
#define debug(lvl, x...) do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0)
|
||||
|
||||
static inline int ffi_struct_type(ffi_type *t)
|
||||
{
|
||||
size_t sz = t->size;
|
||||
|
||||
/* Small structure results are passed in registers,
|
||||
larger ones are passed by pointer. Note that
|
||||
small structures of size 2, 4 and 8 differ from
|
||||
the corresponding integer types in that they have
|
||||
different alignment requirements. */
|
||||
|
||||
if (sz <= 1)
|
||||
return FFI_TYPE_UINT8;
|
||||
else if (sz == 2)
|
||||
return FFI_TYPE_SMALL_STRUCT2;
|
||||
else if (sz == 3)
|
||||
return FFI_TYPE_SMALL_STRUCT3;
|
||||
else if (sz == 4)
|
||||
return FFI_TYPE_SMALL_STRUCT4;
|
||||
else if (sz == 5)
|
||||
return FFI_TYPE_SMALL_STRUCT5;
|
||||
else if (sz == 6)
|
||||
return FFI_TYPE_SMALL_STRUCT6;
|
||||
else if (sz == 7)
|
||||
return FFI_TYPE_SMALL_STRUCT7;
|
||||
else if (sz <= 8)
|
||||
return FFI_TYPE_SMALL_STRUCT8;
|
||||
else
|
||||
return FFI_TYPE_STRUCT; /* else, we pass it by pointer. */
|
||||
}
|
||||
|
||||
/* PA has a downward growing stack, which looks like this:
|
||||
|
||||
Offset
|
||||
[ Variable args ]
|
||||
SP = (4*(n+9)) arg word N
|
||||
...
|
||||
SP-52 arg word 4
|
||||
[ Fixed args ]
|
||||
SP-48 arg word 3
|
||||
SP-44 arg word 2
|
||||
SP-40 arg word 1
|
||||
SP-36 arg word 0
|
||||
[ Frame marker ]
|
||||
...
|
||||
SP-20 RP
|
||||
SP-4 previous SP
|
||||
|
||||
The first four argument words on the stack are reserved for use by
|
||||
the callee. Instead, the general and floating registers replace
|
||||
the first four argument slots. Non FP arguments are passed solely
|
||||
in the general registers. FP arguments are passed in both general
|
||||
and floating registers when using libffi.
|
||||
|
||||
Non-FP 32-bit args are passed in gr26, gr25, gr24 and gr23.
|
||||
Non-FP 64-bit args are passed in register pairs, starting
|
||||
on an odd numbered register (i.e. r25+r26 and r23+r24).
|
||||
FP 32-bit arguments are passed in fr4L, fr5L, fr6L and fr7L.
|
||||
FP 64-bit arguments are passed in fr5 and fr7.
|
||||
|
||||
The registers are allocated in the same manner as stack slots.
|
||||
This allows the callee to save its arguments on the stack if
|
||||
necessary:
|
||||
|
||||
arg word 3 -> gr23 or fr7L
|
||||
arg word 2 -> gr24 or fr6L or fr7R
|
||||
arg word 1 -> gr25 or fr5L
|
||||
arg word 0 -> gr26 or fr4L or fr5R
|
||||
|
||||
Note that fr4R and fr6R are never used for arguments (i.e.,
|
||||
doubles are not passed in fr4 or fr6).
|
||||
|
||||
The rest of the arguments are passed on the stack starting at SP-52,
|
||||
but 64-bit arguments need to be aligned to an 8-byte boundary
|
||||
|
||||
This means we can have holes either in the register allocation,
|
||||
or in the stack. */
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
has been allocated for the function's arguments
|
||||
|
||||
The following code will put everything into the stack frame
|
||||
(which was allocated by the asm routine), and on return
|
||||
the asm routine will load the arguments that should be
|
||||
passed by register into the appropriate registers
|
||||
|
||||
NOTE: We load floating point args in this function... that means we
|
||||
assume gcc will not mess with fp regs in here. */
|
||||
|
||||
void ffi_prep_args_pa32(UINT32 *stack, extended_cif *ecif, unsigned bytes)
|
||||
{
|
||||
register unsigned int i;
|
||||
register ffi_type **p_arg;
|
||||
register void **p_argv;
|
||||
unsigned int slot = FIRST_ARG_SLOT;
|
||||
char *dest_cpy;
|
||||
size_t len;
|
||||
|
||||
debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__, stack,
|
||||
ecif, bytes);
|
||||
|
||||
p_arg = ecif->cif->arg_types;
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = 0; i < ecif->cif->nargs; i++)
|
||||
{
|
||||
int type = (*p_arg)->type;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(SINT32 *)(stack - slot) = *(SINT8 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(UINT32 *)(stack - slot) = *(UINT8 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(SINT32 *)(stack - slot) = *(SINT16 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(UINT32 *)(stack - slot) = *(UINT16 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_POINTER:
|
||||
debug(3, "Storing UINT32 %u in slot %u\n", *(UINT32 *)(*p_argv),
|
||||
slot);
|
||||
*(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
/* Align slot for 64-bit type. */
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
*(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
/* First 4 args go in fr4L - fr7L. */
|
||||
debug(3, "Storing UINT32(float) in slot %u\n", slot);
|
||||
*(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
|
||||
switch (slot - FIRST_ARG_SLOT)
|
||||
{
|
||||
/* First 4 args go in fr4L - fr7L. */
|
||||
case 0: fldw(stack - slot, fr4); break;
|
||||
case 1: fldw(stack - slot, fr5); break;
|
||||
case 2: fldw(stack - slot, fr6); break;
|
||||
case 3: fldw(stack - slot, fr7); break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
/* Align slot for 64-bit type. */
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
debug(3, "Storing UINT64(double) at slot %u\n", slot);
|
||||
*(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
|
||||
switch (slot - FIRST_ARG_SLOT)
|
||||
{
|
||||
/* First 2 args go in fr5, fr7. */
|
||||
case 1: fldd(stack - slot, fr5); break;
|
||||
case 3: fldd(stack - slot, fr7); break;
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef PA_HPUX
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* Long doubles are passed in the same manner as structures
|
||||
larger than 8 bytes. */
|
||||
*(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
|
||||
/* Structs smaller or equal than 4 bytes are passed in one
|
||||
register. Structs smaller or equal 8 bytes are passed in two
|
||||
registers. Larger structures are passed by pointer. */
|
||||
|
||||
len = (*p_arg)->size;
|
||||
if (len <= 4)
|
||||
{
|
||||
dest_cpy = (char *)(stack - slot) + 4 - len;
|
||||
memcpy(dest_cpy, (char *)*p_argv, len);
|
||||
}
|
||||
else if (len <= 8)
|
||||
{
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
dest_cpy = (char *)(stack - slot) + 8 - len;
|
||||
memcpy(dest_cpy, (char *)*p_argv, len);
|
||||
}
|
||||
else
|
||||
*(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
|
||||
slot++;
|
||||
p_arg++;
|
||||
p_argv++;
|
||||
}
|
||||
|
||||
/* Make sure we didn't mess up and scribble on the stack. */
|
||||
{
|
||||
unsigned int n;
|
||||
|
||||
debug(5, "Stack setup:\n");
|
||||
for (n = 0; n < (bytes + 3) / 4; n++)
|
||||
{
|
||||
if ((n%4) == 0) { debug(5, "\n%08x: ", (unsigned int)(stack - n)); }
|
||||
debug(5, "%08x ", *(stack - n));
|
||||
}
|
||||
debug(5, "\n");
|
||||
}
|
||||
|
||||
FFI_ASSERT(slot * 4 <= bytes);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void ffi_size_stack_pa32(ffi_cif *cif)
|
||||
{
|
||||
ffi_type **ptr;
|
||||
int i;
|
||||
int z = 0; /* # stack slots */
|
||||
|
||||
for (ptr = cif->arg_types, i = 0; i < cif->nargs; ptr++, i++)
|
||||
{
|
||||
int type = (*ptr)->type;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_DOUBLE:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
z += 2 + (z & 1); /* must start on even regs, so we may waste one */
|
||||
break;
|
||||
|
||||
#ifdef PA_HPUX
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
#endif
|
||||
case FFI_TYPE_STRUCT:
|
||||
z += 1; /* pass by ptr, callee will copy */
|
||||
break;
|
||||
|
||||
default: /* <= 32-bit values */
|
||||
z++;
|
||||
}
|
||||
}
|
||||
|
||||
/* We can fit up to 6 args in the default 64-byte stack frame,
|
||||
if we need more, we need more stack. */
|
||||
if (z <= 6)
|
||||
cif->bytes = MIN_STACK_SIZE; /* min stack size */
|
||||
else
|
||||
cif->bytes = 64 + ROUND_UP((z - 6) * sizeof(UINT32), MIN_STACK_SIZE);
|
||||
|
||||
debug(3, "Calculated stack size is %u bytes\n", cif->bytes);
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing. */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
|
||||
#ifdef PA_HPUX
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* Long doubles are treated like a structure. */
|
||||
cif->flags = FFI_TYPE_STRUCT;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* For the return type we have to check the size of the structures.
|
||||
If the size is smaller or equal 4 bytes, the result is given back
|
||||
in one register. If the size is smaller or equal 8 bytes than we
|
||||
return the result in two registers. But if the size is bigger than
|
||||
8 bytes, we work with pointers. */
|
||||
cif->flags = ffi_struct_type(cif->rtype);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
cif->flags = FFI_TYPE_UINT64;
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Lucky us, because of the unique PA ABI we get to do our
|
||||
own stack sizing. */
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_PA32:
|
||||
ffi_size_stack_pa32(cif);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern void ffi_call_pa32(void (*)(UINT32 *, extended_cif *, unsigned),
|
||||
extended_cif *, unsigned, unsigned, unsigned *,
|
||||
void (*fn)(void));
|
||||
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(void), 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
|
||||
#ifdef PA_HPUX
|
||||
&& (cif->rtype->type == FFI_TYPE_STRUCT
|
||||
|| cif->rtype->type == FFI_TYPE_LONGDOUBLE))
|
||||
#else
|
||||
&& cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
#endif
|
||||
{
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_PA32:
|
||||
debug(3, "Calling ffi_call_pa32: ecif=%p, bytes=%u, flags=%u, rvalue=%p, fn=%p\n", &ecif, cif->bytes, cif->flags, ecif.rvalue, (void *)fn);
|
||||
ffi_call_pa32(ffi_prep_args_pa32, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if FFI_CLOSURES
|
||||
/* This is more-or-less an inverse of ffi_call -- we have arguments on
|
||||
the stack, and we need to fill them into a cif structure and invoke
|
||||
the user function. This really ought to be in asm to make sure
|
||||
the compiler doesn't do things we don't expect. */
|
||||
ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
void **avalue;
|
||||
void *rvalue;
|
||||
UINT32 ret[2]; /* function can return up to 64-bits in registers */
|
||||
ffi_type **p_arg;
|
||||
char *tmp;
|
||||
int i, avn;
|
||||
unsigned int slot = FIRST_ARG_SLOT;
|
||||
register UINT32 r28 asm("r28");
|
||||
|
||||
cif = closure->cif;
|
||||
|
||||
/* If returning via structure, callee will write to our pointer. */
|
||||
if (cif->flags == FFI_TYPE_STRUCT)
|
||||
rvalue = (void *)r28;
|
||||
else
|
||||
rvalue = &ret[0];
|
||||
|
||||
avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG);
|
||||
avn = cif->nargs;
|
||||
p_arg = cif->arg_types;
|
||||
|
||||
for (i = 0; i < avn; i++)
|
||||
{
|
||||
int type = (*p_arg)->type;
|
||||
|
||||
switch (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_POINTER:
|
||||
avalue[i] = (char *)(stack - slot) + sizeof(UINT32) - (*p_arg)->size;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
avalue[i] = (void *)(stack - slot);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
#ifdef PA_LINUX
|
||||
/* The closure call is indirect. In Linux, floating point
|
||||
arguments in indirect calls with a prototype are passed
|
||||
in the floating point registers instead of the general
|
||||
registers. So, we need to replace what was previously
|
||||
stored in the current slot with the value in the
|
||||
corresponding floating point register. */
|
||||
switch (slot - FIRST_ARG_SLOT)
|
||||
{
|
||||
case 0: fstw(fr4, (void *)(stack - slot)); break;
|
||||
case 1: fstw(fr5, (void *)(stack - slot)); break;
|
||||
case 2: fstw(fr6, (void *)(stack - slot)); break;
|
||||
case 3: fstw(fr7, (void *)(stack - slot)); break;
|
||||
}
|
||||
#endif
|
||||
avalue[i] = (void *)(stack - slot);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
#ifdef PA_LINUX
|
||||
/* See previous comment for FFI_TYPE_FLOAT. */
|
||||
switch (slot - FIRST_ARG_SLOT)
|
||||
{
|
||||
case 1: fstd(fr5, (void *)(stack - slot)); break;
|
||||
case 3: fstd(fr7, (void *)(stack - slot)); break;
|
||||
}
|
||||
#endif
|
||||
avalue[i] = (void *)(stack - slot);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* Structs smaller or equal than 4 bytes are passed in one
|
||||
register. Structs smaller or equal 8 bytes are passed in two
|
||||
registers. Larger structures are passed by pointer. */
|
||||
if((*p_arg)->size <= 4)
|
||||
{
|
||||
avalue[i] = (void *)(stack - slot) + sizeof(UINT32) -
|
||||
(*p_arg)->size;
|
||||
}
|
||||
else if ((*p_arg)->size <= 8)
|
||||
{
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
avalue[i] = (void *)(stack - slot) + sizeof(UINT64) -
|
||||
(*p_arg)->size;
|
||||
}
|
||||
else
|
||||
avalue[i] = (void *) *(stack - slot);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
|
||||
slot++;
|
||||
p_arg++;
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0],
|
||||
ret[1]);
|
||||
|
||||
/* Store the result using the lower 2 bytes of the flags. */
|
||||
switch (cif->flags)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
*(stack - FIRST_ARG_SLOT) = (UINT8)(ret[0] >> 24);
|
||||
break;
|
||||
case FFI_TYPE_SINT8:
|
||||
*(stack - FIRST_ARG_SLOT) = (SINT8)(ret[0] >> 24);
|
||||
break;
|
||||
case FFI_TYPE_UINT16:
|
||||
*(stack - FIRST_ARG_SLOT) = (UINT16)(ret[0] >> 16);
|
||||
break;
|
||||
case FFI_TYPE_SINT16:
|
||||
*(stack - FIRST_ARG_SLOT) = (SINT16)(ret[0] >> 16);
|
||||
break;
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
*(stack - FIRST_ARG_SLOT) = ret[0];
|
||||
break;
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
*(stack - FIRST_ARG_SLOT) = ret[0];
|
||||
*(stack - FIRST_ARG_SLOT - 1) = ret[1];
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
fldd(rvalue, fr4);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
fldw(rvalue, fr4);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* Don't need a return value, done by caller. */
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SMALL_STRUCT2:
|
||||
case FFI_TYPE_SMALL_STRUCT3:
|
||||
case FFI_TYPE_SMALL_STRUCT4:
|
||||
tmp = (void*)(stack - FIRST_ARG_SLOT);
|
||||
tmp += 4 - cif->rtype->size;
|
||||
memcpy((void*)tmp, &ret[0], cif->rtype->size);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SMALL_STRUCT5:
|
||||
case FFI_TYPE_SMALL_STRUCT6:
|
||||
case FFI_TYPE_SMALL_STRUCT7:
|
||||
case FFI_TYPE_SMALL_STRUCT8:
|
||||
{
|
||||
unsigned int ret2[2];
|
||||
int off;
|
||||
|
||||
/* Right justify ret[0] and ret[1] */
|
||||
switch (cif->flags)
|
||||
{
|
||||
case FFI_TYPE_SMALL_STRUCT5: off = 3; break;
|
||||
case FFI_TYPE_SMALL_STRUCT6: off = 2; break;
|
||||
case FFI_TYPE_SMALL_STRUCT7: off = 1; break;
|
||||
default: off = 0; break;
|
||||
}
|
||||
|
||||
memset (ret2, 0, sizeof (ret2));
|
||||
memcpy ((char *)ret2 + off, ret, 8 - off);
|
||||
|
||||
*(stack - FIRST_ARG_SLOT) = ret2[0];
|
||||
*(stack - FIRST_ARG_SLOT - 1) = ret2[1];
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
case FFI_TYPE_VOID:
|
||||
break;
|
||||
|
||||
default:
|
||||
debug(0, "assert with cif->flags: %d\n",cif->flags);
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/* Fill in a closure to refer to the specified fun and user_data.
|
||||
cif specifies the argument and result types for fun.
|
||||
The cif must already be prep'ed. */
|
||||
|
||||
extern void ffi_closure_pa32(void);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
UINT32 *tramp = (UINT32 *)(closure->tramp);
|
||||
#ifdef PA_HPUX
|
||||
UINT32 *tmp;
|
||||
#endif
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_PA32);
|
||||
|
||||
/* Make a small trampoline that will branch to our
|
||||
handler function. Use PC-relative addressing. */
|
||||
|
||||
#ifdef PA_LINUX
|
||||
tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */
|
||||
tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */
|
||||
tramp[2] = 0x4aa10028; /* ldw 20(%r21),%r1 ; load plabel */
|
||||
tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */
|
||||
tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */
|
||||
tramp[5] = 0xeac0c000; /* bv%r0(%r22) ; branch to handler */
|
||||
tramp[6] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */
|
||||
tramp[7] = ((UINT32)(ffi_closure_pa32) & ~2);
|
||||
|
||||
/* Flush d/icache -- have to flush up 2 two lines because of
|
||||
alignment. */
|
||||
__asm__ volatile(
|
||||
"fdc 0(%0)\n\t"
|
||||
"fdc %1(%0)\n\t"
|
||||
"fic 0(%%sr4, %0)\n\t"
|
||||
"fic %1(%%sr4, %0)\n\t"
|
||||
"sync\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n"
|
||||
:
|
||||
: "r"((unsigned long)tramp & ~31),
|
||||
"r"(32 /* stride */)
|
||||
: "memory");
|
||||
#endif
|
||||
|
||||
#ifdef PA_HPUX
|
||||
tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */
|
||||
tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */
|
||||
tramp[2] = 0x4aa10038; /* ldw 28(%r21),%r1 ; load plabel */
|
||||
tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */
|
||||
tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */
|
||||
tramp[5] = 0x02c010b4; /* ldsid (%r22),%r20 ; load space id */
|
||||
tramp[6] = 0x00141820; /* mtsp %r20,%sr0 ; into %sr0 */
|
||||
tramp[7] = 0xe2c00000; /* be 0(%sr0,%r22) ; branch to handler */
|
||||
tramp[8] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */
|
||||
tramp[9] = ((UINT32)(ffi_closure_pa32) & ~2);
|
||||
|
||||
/* Flush d/icache -- have to flush three lines because of alignment. */
|
||||
__asm__ volatile(
|
||||
"copy %1,%0\n\t"
|
||||
"fdc,m %2(%0)\n\t"
|
||||
"fdc,m %2(%0)\n\t"
|
||||
"fdc,m %2(%0)\n\t"
|
||||
"ldsid (%1),%0\n\t"
|
||||
"mtsp %0,%%sr0\n\t"
|
||||
"copy %1,%0\n\t"
|
||||
"fic,m %2(%%sr0,%0)\n\t"
|
||||
"fic,m %2(%%sr0,%0)\n\t"
|
||||
"fic,m %2(%%sr0,%0)\n\t"
|
||||
"sync\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n"
|
||||
: "=&r" ((unsigned long)tmp)
|
||||
: "r" ((unsigned long)tramp & ~31),
|
||||
"r" (32/* stride */)
|
||||
: "memory");
|
||||
#endif
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
#endif
|
||||
77
src/pa/.svn/text-base/ffitarget.h.svn-base
Normal file
77
src/pa/.svn/text-base/ffitarget.h.svn-base
Normal file
@@ -0,0 +1,77 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for hppa.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
/* ---- System specific configurations ----------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
|
||||
#ifdef PA_LINUX
|
||||
FFI_PA32,
|
||||
FFI_DEFAULT_ABI = FFI_PA32,
|
||||
#endif
|
||||
|
||||
#ifdef PA_HPUX
|
||||
FFI_PA32,
|
||||
FFI_DEFAULT_ABI = FFI_PA32,
|
||||
#endif
|
||||
|
||||
#ifdef PA64_HPUX
|
||||
#error "PA64_HPUX FFI is not yet implemented"
|
||||
FFI_PA64,
|
||||
FFI_DEFAULT_ABI = FFI_PA64,
|
||||
#endif
|
||||
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#ifdef PA_LINUX
|
||||
#define FFI_TRAMPOLINE_SIZE 32
|
||||
#else
|
||||
#define FFI_TRAMPOLINE_SIZE 40
|
||||
#endif
|
||||
|
||||
#define FFI_TYPE_SMALL_STRUCT2 -1
|
||||
#define FFI_TYPE_SMALL_STRUCT3 -2
|
||||
#define FFI_TYPE_SMALL_STRUCT4 -3
|
||||
#define FFI_TYPE_SMALL_STRUCT5 -4
|
||||
#define FFI_TYPE_SMALL_STRUCT6 -5
|
||||
#define FFI_TYPE_SMALL_STRUCT7 -6
|
||||
#define FFI_TYPE_SMALL_STRUCT8 -7
|
||||
#endif
|
||||
368
src/pa/.svn/text-base/hpux32.S.svn-base
Normal file
368
src/pa/.svn/text-base/hpux32.S.svn-base
Normal file
@@ -0,0 +1,368 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
hpux32.S - Copyright (c) 2006 Free Software Foundation, Inc.
|
||||
(c) 2008 Red Hat, Inc.
|
||||
based on src/pa/linux.S
|
||||
|
||||
HP-UX PA 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
.LEVEL 1.1
|
||||
.SPACE $PRIVATE$
|
||||
.IMPORT $global$,DATA
|
||||
.IMPORT $$dyncall,MILLICODE
|
||||
.SUBSPA $DATA$
|
||||
.align 4
|
||||
|
||||
/* void ffi_call_pa32(void (*)(char *, extended_cif *),
|
||||
extended_cif *ecif,
|
||||
unsigned bytes,
|
||||
unsigned flags,
|
||||
unsigned *rvalue,
|
||||
void (*fn)(void));
|
||||
*/
|
||||
|
||||
.export ffi_call_pa32,ENTRY,PRIV_LEV=3
|
||||
.import ffi_prep_args_pa32,CODE
|
||||
|
||||
.SPACE $TEXT$
|
||||
.SUBSPA $CODE$
|
||||
.align 4
|
||||
|
||||
L$FB1
|
||||
ffi_call_pa32
|
||||
.proc
|
||||
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
|
||||
.entry
|
||||
stw %rp, -20(%sp)
|
||||
copy %r3, %r1
|
||||
L$CFI11
|
||||
copy %sp, %r3
|
||||
L$CFI12
|
||||
|
||||
/* Setup the stack for calling prep_args...
|
||||
We want the stack to look like this:
|
||||
|
||||
[ Previous stack ] <- %r3
|
||||
|
||||
[ 64-bytes register save area ] <- %r4
|
||||
|
||||
[ Stack space for actual call, passed as ] <- %arg0
|
||||
[ arg0 to ffi_prep_args_pa32 ]
|
||||
|
||||
[ Stack for calling prep_args ] <- %sp
|
||||
*/
|
||||
|
||||
stwm %r1, 64(%sp)
|
||||
stw %r4, 12(%r3)
|
||||
L$CFI13
|
||||
copy %sp, %r4
|
||||
|
||||
addl %arg2, %r4, %arg0 ; arg stack
|
||||
stw %arg3, -48(%r3) ; save flags we need it later
|
||||
|
||||
/* Call prep_args:
|
||||
%arg0(stack) -- set up above
|
||||
%arg1(ecif) -- same as incoming param
|
||||
%arg2(bytes) -- same as incoming param */
|
||||
bl ffi_prep_args_pa32,%r2
|
||||
ldo 64(%arg0), %sp
|
||||
ldo -64(%sp), %sp
|
||||
|
||||
/* now %sp should point where %arg0 was pointing. */
|
||||
|
||||
/* Load the arguments that should be passed in registers
|
||||
The fp args are loaded by the prep_args function. */
|
||||
ldw -36(%sp), %arg0
|
||||
ldw -40(%sp), %arg1
|
||||
ldw -44(%sp), %arg2
|
||||
ldw -48(%sp), %arg3
|
||||
|
||||
/* in case the function is going to return a structure
|
||||
we need to give it a place to put the result. */
|
||||
ldw -52(%r3), %ret0 ; %ret0 <- rvalue
|
||||
ldw -56(%r3), %r22 ; %r22 <- function to call
|
||||
bl $$dyncall, %r31 ; Call the user function
|
||||
copy %r31, %rp
|
||||
|
||||
/* Prepare to store the result; we need to recover flags and rvalue. */
|
||||
ldw -48(%r3), %r21 ; r21 <- flags
|
||||
ldw -52(%r3), %r20 ; r20 <- rvalue
|
||||
|
||||
/* Store the result according to the return type. The most
|
||||
likely types should come first. */
|
||||
|
||||
L$checkint
|
||||
comib,<>,n FFI_TYPE_INT, %r21, L$checkint8
|
||||
b L$done
|
||||
stw %ret0, 0(%r20)
|
||||
|
||||
L$checkint8
|
||||
comib,<>,n FFI_TYPE_UINT8, %r21, L$checkint16
|
||||
b L$done
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
L$checkint16
|
||||
comib,<>,n FFI_TYPE_UINT16, %r21, L$checkdbl
|
||||
b L$done
|
||||
sth %ret0, 0(%r20)
|
||||
|
||||
L$checkdbl
|
||||
comib,<>,n FFI_TYPE_DOUBLE, %r21, L$checkfloat
|
||||
b L$done
|
||||
fstd %fr4,0(%r20)
|
||||
|
||||
L$checkfloat
|
||||
comib,<>,n FFI_TYPE_FLOAT, %r21, L$checkll
|
||||
b L$done
|
||||
fstw %fr4L,0(%r20)
|
||||
|
||||
L$checkll
|
||||
comib,<>,n FFI_TYPE_UINT64, %r21, L$checksmst2
|
||||
stw %ret0, 0(%r20)
|
||||
b L$done
|
||||
stw %ret1, 4(%r20)
|
||||
|
||||
L$checksmst2
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, L$checksmst3
|
||||
/* 2-byte structs are returned in ret0 as ????xxyy. */
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b L$done
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
L$checksmst3
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, L$checksmst4
|
||||
/* 3-byte structs are returned in ret0 as ??xxyyzz. */
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b L$done
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
L$checksmst4
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT4, %r21, L$checksmst5
|
||||
/* 4-byte structs are returned in ret0 as wwxxyyzz. */
|
||||
extru %ret0, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b L$done
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
L$checksmst5
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT5, %r21, L$checksmst6
|
||||
/* 5 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
5: ??????aa bbccddee */
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b L$done
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
L$checksmst6
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT6, %r21, L$checksmst7
|
||||
/* 6 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
6: ????aabb ccddeeff */
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b L$done
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
L$checksmst7
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT7, %r21, L$checksmst8
|
||||
/* 7 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
7: ??aabbcc ddeeffgg */
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b L$done
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
L$checksmst8
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT8, %r21, L$done
|
||||
/* 8 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
8: aabbccdd eeffgghh */
|
||||
extru %ret0, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
L$done
|
||||
/* all done, return */
|
||||
copy %r4, %sp ; pop arg stack
|
||||
ldw 12(%r3), %r4
|
||||
ldwm -64(%sp), %r3 ; .. and pop stack
|
||||
ldw -20(%sp), %rp
|
||||
bv %r0(%rp)
|
||||
nop
|
||||
.exit
|
||||
.procend
|
||||
L$FE1
|
||||
|
||||
/* void ffi_closure_pa32(void);
|
||||
Called with closure argument in %r21 */
|
||||
|
||||
.SPACE $TEXT$
|
||||
.SUBSPA $CODE$
|
||||
.export ffi_closure_pa32,ENTRY,PRIV_LEV=3,RTNVAL=GR
|
||||
.import ffi_closure_inner_pa32,CODE
|
||||
.align 4
|
||||
L$FB2
|
||||
ffi_closure_pa32
|
||||
.proc
|
||||
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
|
||||
.entry
|
||||
|
||||
stw %rp, -20(%sp)
|
||||
copy %r3, %r1
|
||||
L$CFI21
|
||||
copy %sp, %r3
|
||||
L$CFI22
|
||||
stwm %r1, 64(%sp)
|
||||
|
||||
/* Put arguments onto the stack and call ffi_closure_inner. */
|
||||
stw %arg0, -36(%r3)
|
||||
stw %arg1, -40(%r3)
|
||||
stw %arg2, -44(%r3)
|
||||
stw %arg3, -48(%r3)
|
||||
|
||||
copy %r21, %arg0
|
||||
bl ffi_closure_inner_pa32, %r2
|
||||
copy %r3, %arg1
|
||||
ldwm -64(%sp), %r3
|
||||
ldw -20(%sp), %rp
|
||||
ldw -36(%sp), %ret0
|
||||
bv %r0(%rp)
|
||||
ldw -40(%sp), %ret1
|
||||
.exit
|
||||
.procend
|
||||
L$FE2:
|
||||
|
||||
.SPACE $PRIVATE$
|
||||
.SUBSPA $DATA$
|
||||
|
||||
.align 4
|
||||
.EXPORT _GLOBAL__F_ffi_call_pa32,DATA
|
||||
_GLOBAL__F_ffi_call_pa32
|
||||
L$frame1:
|
||||
.word L$ECIE1-L$SCIE1 ;# Length of Common Information Entry
|
||||
L$SCIE1:
|
||||
.word 0x0 ;# CIE Identifier Tag
|
||||
.byte 0x1 ;# CIE Version
|
||||
.ascii "\0" ;# CIE Augmentation
|
||||
.uleb128 0x1 ;# CIE Code Alignment Factor
|
||||
.sleb128 4 ;# CIE Data Alignment Factor
|
||||
.byte 0x2 ;# CIE RA Column
|
||||
.byte 0xc ;# DW_CFA_def_cfa
|
||||
.uleb128 0x1e
|
||||
.uleb128 0x0
|
||||
.align 4
|
||||
L$ECIE1:
|
||||
L$SFDE1:
|
||||
.word L$EFDE1-L$ASFDE1 ;# FDE Length
|
||||
L$ASFDE1:
|
||||
.word L$ASFDE1-L$frame1 ;# FDE CIE offset
|
||||
.word L$FB1 ;# FDE initial location
|
||||
.word L$FE1-L$FB1 ;# FDE address range
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word L$CFI11-L$FB1
|
||||
.byte 0x83 ;# DW_CFA_offset, column 0x3
|
||||
.uleb128 0x0
|
||||
.byte 0x11 ;# DW_CFA_offset_extended_sf; save r2 at [r30-20]
|
||||
.uleb128 0x2
|
||||
.sleb128 -5
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word L$CFI12-L$CFI11
|
||||
.byte 0xd ;# DW_CFA_def_cfa_register = r3
|
||||
.uleb128 0x3
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word L$CFI13-L$CFI12
|
||||
.byte 0x84 ;# DW_CFA_offset, column 0x4
|
||||
.uleb128 0x3
|
||||
|
||||
.align 4
|
||||
L$EFDE1:
|
||||
|
||||
L$SFDE2:
|
||||
.word L$EFDE2-L$ASFDE2 ;# FDE Length
|
||||
L$ASFDE2:
|
||||
.word L$ASFDE2-L$frame1 ;# FDE CIE offset
|
||||
.word L$FB2 ;# FDE initial location
|
||||
.word L$FE2-L$FB2 ;# FDE address range
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word L$CFI21-L$FB2
|
||||
.byte 0x83 ;# DW_CFA_offset, column 0x3
|
||||
.uleb128 0x0
|
||||
.byte 0x11 ;# DW_CFA_offset_extended_sf
|
||||
.uleb128 0x2
|
||||
.sleb128 -5
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word L$CFI22-L$CFI21
|
||||
.byte 0xd ;# DW_CFA_def_cfa_register = r3
|
||||
.uleb128 0x3
|
||||
|
||||
.align 4
|
||||
L$EFDE2:
|
||||
357
src/pa/.svn/text-base/linux.S.svn-base
Normal file
357
src/pa/.svn/text-base/linux.S.svn-base
Normal file
@@ -0,0 +1,357 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
linux.S - (c) 2003-2004 Randolph Chung <tausq@debian.org>
|
||||
(c) 2008 Red Hat, Inc.
|
||||
|
||||
HPPA 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 RENESAS TECHNOLOGY 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
.text
|
||||
.level 1.1
|
||||
.align 4
|
||||
|
||||
/* void ffi_call_pa32(void (*)(char *, extended_cif *),
|
||||
extended_cif *ecif,
|
||||
unsigned bytes,
|
||||
unsigned flags,
|
||||
unsigned *rvalue,
|
||||
void (*fn)(void));
|
||||
*/
|
||||
|
||||
.export ffi_call_pa32,code
|
||||
.import ffi_prep_args_pa32,code
|
||||
|
||||
.type ffi_call_pa32, @function
|
||||
.LFB1:
|
||||
ffi_call_pa32:
|
||||
.proc
|
||||
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
|
||||
.entry
|
||||
stw %rp, -20(%sp)
|
||||
copy %r3, %r1
|
||||
.LCFI11:
|
||||
|
||||
copy %sp, %r3
|
||||
.LCFI12:
|
||||
|
||||
/* Setup the stack for calling prep_args...
|
||||
We want the stack to look like this:
|
||||
|
||||
[ Previous stack ] <- %r3
|
||||
|
||||
[ 64-bytes register save area ] <- %r4
|
||||
|
||||
[ Stack space for actual call, passed as ] <- %arg0
|
||||
[ arg0 to ffi_prep_args_pa32 ]
|
||||
|
||||
[ Stack for calling prep_args ] <- %sp
|
||||
*/
|
||||
|
||||
stwm %r1, 64(%sp)
|
||||
stw %r4, 12(%r3)
|
||||
.LCFI13:
|
||||
copy %sp, %r4
|
||||
|
||||
addl %arg2, %r4, %arg0 /* arg stack */
|
||||
stw %arg3, -48(%r3) /* save flags; we need it later */
|
||||
|
||||
/* Call prep_args:
|
||||
%arg0(stack) -- set up above
|
||||
%arg1(ecif) -- same as incoming param
|
||||
%arg2(bytes) -- same as incoming param */
|
||||
bl ffi_prep_args_pa32,%r2
|
||||
ldo 64(%arg0), %sp
|
||||
ldo -64(%sp), %sp
|
||||
|
||||
/* now %sp should point where %arg0 was pointing. */
|
||||
|
||||
/* Load the arguments that should be passed in registers
|
||||
The fp args were loaded by the prep_args function. */
|
||||
ldw -36(%sp), %arg0
|
||||
ldw -40(%sp), %arg1
|
||||
ldw -44(%sp), %arg2
|
||||
ldw -48(%sp), %arg3
|
||||
|
||||
/* in case the function is going to return a structure
|
||||
we need to give it a place to put the result. */
|
||||
ldw -52(%r3), %ret0 /* %ret0 <- rvalue */
|
||||
ldw -56(%r3), %r22 /* %r22 <- function to call */
|
||||
bl $$dyncall, %r31 /* Call the user function */
|
||||
copy %r31, %rp
|
||||
|
||||
/* Prepare to store the result; we need to recover flags and rvalue. */
|
||||
ldw -48(%r3), %r21 /* r21 <- flags */
|
||||
ldw -52(%r3), %r20 /* r20 <- rvalue */
|
||||
|
||||
/* Store the result according to the return type. */
|
||||
|
||||
.Lcheckint:
|
||||
comib,<>,n FFI_TYPE_INT, %r21, .Lcheckint8
|
||||
b .Ldone
|
||||
stw %ret0, 0(%r20)
|
||||
|
||||
.Lcheckint8:
|
||||
comib,<>,n FFI_TYPE_UINT8, %r21, .Lcheckint16
|
||||
b .Ldone
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
.Lcheckint16:
|
||||
comib,<>,n FFI_TYPE_UINT16, %r21, .Lcheckdbl
|
||||
b .Ldone
|
||||
sth %ret0, 0(%r20)
|
||||
|
||||
.Lcheckdbl:
|
||||
comib,<>,n FFI_TYPE_DOUBLE, %r21, .Lcheckfloat
|
||||
b .Ldone
|
||||
fstd %fr4,0(%r20)
|
||||
|
||||
.Lcheckfloat:
|
||||
comib,<>,n FFI_TYPE_FLOAT, %r21, .Lcheckll
|
||||
b .Ldone
|
||||
fstw %fr4L,0(%r20)
|
||||
|
||||
.Lcheckll:
|
||||
comib,<>,n FFI_TYPE_UINT64, %r21, .Lchecksmst2
|
||||
stw %ret0, 0(%r20)
|
||||
b .Ldone
|
||||
stw %ret1, 4(%r20)
|
||||
|
||||
.Lchecksmst2:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, .Lchecksmst3
|
||||
/* 2-byte structs are returned in ret0 as ????xxyy. */
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
.Lchecksmst3:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, .Lchecksmst4
|
||||
/* 3-byte structs are returned in ret0 as ??xxyyzz. */
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
.Lchecksmst4:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT4, %r21, .Lchecksmst5
|
||||
/* 4-byte structs are returned in ret0 as wwxxyyzz. */
|
||||
extru %ret0, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
.Lchecksmst5:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT5, %r21, .Lchecksmst6
|
||||
/* 5 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
5: ??????aa bbccddee */
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
.Lchecksmst6:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT6, %r21, .Lchecksmst7
|
||||
/* 6 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
6: ????aabb ccddeeff */
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
.Lchecksmst7:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT7, %r21, .Lchecksmst8
|
||||
/* 7 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
7: ??aabbcc ddeeffgg */
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
.Lchecksmst8:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT8, %r21, .Ldone
|
||||
/* 8 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
8: aabbccdd eeffgghh */
|
||||
extru %ret0, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
.Ldone:
|
||||
/* all done, return */
|
||||
copy %r4, %sp /* pop arg stack */
|
||||
ldw 12(%r3), %r4
|
||||
ldwm -64(%sp), %r3 /* .. and pop stack */
|
||||
ldw -20(%sp), %rp
|
||||
bv %r0(%rp)
|
||||
nop
|
||||
.exit
|
||||
.procend
|
||||
.LFE1:
|
||||
|
||||
/* void ffi_closure_pa32(void);
|
||||
Called with closure argument in %r21 */
|
||||
.export ffi_closure_pa32,code
|
||||
.import ffi_closure_inner_pa32,code
|
||||
|
||||
.type ffi_closure_pa32, @function
|
||||
.LFB2:
|
||||
ffi_closure_pa32:
|
||||
.proc
|
||||
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
|
||||
.entry
|
||||
|
||||
stw %rp, -20(%sp)
|
||||
.LCFI20:
|
||||
copy %r3, %r1
|
||||
.LCFI21:
|
||||
copy %sp, %r3
|
||||
.LCFI22:
|
||||
stwm %r1, 64(%sp)
|
||||
|
||||
/* Put arguments onto the stack and call ffi_closure_inner. */
|
||||
stw %arg0, -36(%r3)
|
||||
stw %arg1, -40(%r3)
|
||||
stw %arg2, -44(%r3)
|
||||
stw %arg3, -48(%r3)
|
||||
|
||||
copy %r21, %arg0
|
||||
bl ffi_closure_inner_pa32, %r2
|
||||
copy %r3, %arg1
|
||||
|
||||
ldwm -64(%sp), %r3
|
||||
ldw -20(%sp), %rp
|
||||
ldw -36(%sp), %ret0
|
||||
bv %r0(%r2)
|
||||
ldw -40(%sp), %ret1
|
||||
|
||||
.exit
|
||||
.procend
|
||||
.LFE2:
|
||||
|
||||
.section ".eh_frame",EH_FRAME_FLAGS,@progbits
|
||||
.Lframe1:
|
||||
.word .LECIE1-.LSCIE1 ;# Length of Common Information Entry
|
||||
.LSCIE1:
|
||||
.word 0x0 ;# CIE Identifier Tag
|
||||
.byte 0x1 ;# CIE Version
|
||||
.ascii "\0" ;# CIE Augmentation
|
||||
.uleb128 0x1 ;# CIE Code Alignment Factor
|
||||
.sleb128 4 ;# CIE Data Alignment Factor
|
||||
.byte 0x2 ;# CIE RA Column
|
||||
.byte 0xc ;# DW_CFA_def_cfa
|
||||
.uleb128 0x1e
|
||||
.uleb128 0x0
|
||||
.align 4
|
||||
.LECIE1:
|
||||
.LSFDE1:
|
||||
.word .LEFDE1-.LASFDE1 ;# FDE Length
|
||||
.LASFDE1:
|
||||
.word .LASFDE1-.Lframe1 ;# FDE CIE offset
|
||||
.word .LFB1 ;# FDE initial location
|
||||
.word .LFE1-.LFB1 ;# FDE address range
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word .LCFI11-.LFB1
|
||||
.byte 0x83 ;# DW_CFA_offset, column 0x3
|
||||
.uleb128 0x0
|
||||
.byte 0x11 ;# DW_CFA_offset_extended_sf; save r2 at [r30-20]
|
||||
.uleb128 0x2
|
||||
.sleb128 -5
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word .LCFI12-.LCFI11
|
||||
.byte 0xd ;# DW_CFA_def_cfa_register = r3
|
||||
.uleb128 0x3
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word .LCFI13-.LCFI12
|
||||
.byte 0x84 ;# DW_CFA_offset, column 0x4
|
||||
.uleb128 0x3
|
||||
|
||||
.align 4
|
||||
.LEFDE1:
|
||||
|
||||
.LSFDE2:
|
||||
.word .LEFDE2-.LASFDE2 ;# FDE Length
|
||||
.LASFDE2:
|
||||
.word .LASFDE2-.Lframe1 ;# FDE CIE offset
|
||||
.word .LFB2 ;# FDE initial location
|
||||
.word .LFE2-.LFB2 ;# FDE address range
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word .LCFI21-.LFB2
|
||||
.byte 0x83 ;# DW_CFA_offset, column 0x3
|
||||
.uleb128 0x0
|
||||
.byte 0x11 ;# DW_CFA_offset_extended_sf
|
||||
.uleb128 0x2
|
||||
.sleb128 -5
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word .LCFI22-.LCFI21
|
||||
.byte 0xd ;# DW_CFA_def_cfa_register = r3
|
||||
.uleb128 0x3
|
||||
|
||||
.align 4
|
||||
.LEFDE2:
|
||||
709
src/pa/ffi.c
Normal file
709
src/pa/ffi.c
Normal file
@@ -0,0 +1,709 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - (c) 2003-2004 Randolph Chung <tausq@debian.org>
|
||||
(c) 2008 Red Hat, Inc.
|
||||
|
||||
HPPA Foreign Function Interface
|
||||
HP-UX PA ABI support (c) 2006 Free Software Foundation, Inc.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define ROUND_UP(v, a) (((size_t)(v) + (a) - 1) & ~((a) - 1))
|
||||
|
||||
#define MIN_STACK_SIZE 64
|
||||
#define FIRST_ARG_SLOT 9
|
||||
#define DEBUG_LEVEL 0
|
||||
|
||||
#define fldw(addr, fpreg) \
|
||||
__asm__ volatile ("fldw 0(%0), %%" #fpreg "L" : : "r"(addr) : #fpreg)
|
||||
#define fstw(fpreg, addr) \
|
||||
__asm__ volatile ("fstw %%" #fpreg "L, 0(%0)" : : "r"(addr))
|
||||
#define fldd(addr, fpreg) \
|
||||
__asm__ volatile ("fldd 0(%0), %%" #fpreg : : "r"(addr) : #fpreg)
|
||||
#define fstd(fpreg, addr) \
|
||||
__asm__ volatile ("fstd %%" #fpreg "L, 0(%0)" : : "r"(addr))
|
||||
|
||||
#define debug(lvl, x...) do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0)
|
||||
|
||||
static inline int ffi_struct_type(ffi_type *t)
|
||||
{
|
||||
size_t sz = t->size;
|
||||
|
||||
/* Small structure results are passed in registers,
|
||||
larger ones are passed by pointer. Note that
|
||||
small structures of size 2, 4 and 8 differ from
|
||||
the corresponding integer types in that they have
|
||||
different alignment requirements. */
|
||||
|
||||
if (sz <= 1)
|
||||
return FFI_TYPE_UINT8;
|
||||
else if (sz == 2)
|
||||
return FFI_TYPE_SMALL_STRUCT2;
|
||||
else if (sz == 3)
|
||||
return FFI_TYPE_SMALL_STRUCT3;
|
||||
else if (sz == 4)
|
||||
return FFI_TYPE_SMALL_STRUCT4;
|
||||
else if (sz == 5)
|
||||
return FFI_TYPE_SMALL_STRUCT5;
|
||||
else if (sz == 6)
|
||||
return FFI_TYPE_SMALL_STRUCT6;
|
||||
else if (sz == 7)
|
||||
return FFI_TYPE_SMALL_STRUCT7;
|
||||
else if (sz <= 8)
|
||||
return FFI_TYPE_SMALL_STRUCT8;
|
||||
else
|
||||
return FFI_TYPE_STRUCT; /* else, we pass it by pointer. */
|
||||
}
|
||||
|
||||
/* PA has a downward growing stack, which looks like this:
|
||||
|
||||
Offset
|
||||
[ Variable args ]
|
||||
SP = (4*(n+9)) arg word N
|
||||
...
|
||||
SP-52 arg word 4
|
||||
[ Fixed args ]
|
||||
SP-48 arg word 3
|
||||
SP-44 arg word 2
|
||||
SP-40 arg word 1
|
||||
SP-36 arg word 0
|
||||
[ Frame marker ]
|
||||
...
|
||||
SP-20 RP
|
||||
SP-4 previous SP
|
||||
|
||||
The first four argument words on the stack are reserved for use by
|
||||
the callee. Instead, the general and floating registers replace
|
||||
the first four argument slots. Non FP arguments are passed solely
|
||||
in the general registers. FP arguments are passed in both general
|
||||
and floating registers when using libffi.
|
||||
|
||||
Non-FP 32-bit args are passed in gr26, gr25, gr24 and gr23.
|
||||
Non-FP 64-bit args are passed in register pairs, starting
|
||||
on an odd numbered register (i.e. r25+r26 and r23+r24).
|
||||
FP 32-bit arguments are passed in fr4L, fr5L, fr6L and fr7L.
|
||||
FP 64-bit arguments are passed in fr5 and fr7.
|
||||
|
||||
The registers are allocated in the same manner as stack slots.
|
||||
This allows the callee to save its arguments on the stack if
|
||||
necessary:
|
||||
|
||||
arg word 3 -> gr23 or fr7L
|
||||
arg word 2 -> gr24 or fr6L or fr7R
|
||||
arg word 1 -> gr25 or fr5L
|
||||
arg word 0 -> gr26 or fr4L or fr5R
|
||||
|
||||
Note that fr4R and fr6R are never used for arguments (i.e.,
|
||||
doubles are not passed in fr4 or fr6).
|
||||
|
||||
The rest of the arguments are passed on the stack starting at SP-52,
|
||||
but 64-bit arguments need to be aligned to an 8-byte boundary
|
||||
|
||||
This means we can have holes either in the register allocation,
|
||||
or in the stack. */
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
has been allocated for the function's arguments
|
||||
|
||||
The following code will put everything into the stack frame
|
||||
(which was allocated by the asm routine), and on return
|
||||
the asm routine will load the arguments that should be
|
||||
passed by register into the appropriate registers
|
||||
|
||||
NOTE: We load floating point args in this function... that means we
|
||||
assume gcc will not mess with fp regs in here. */
|
||||
|
||||
void ffi_prep_args_pa32(UINT32 *stack, extended_cif *ecif, unsigned bytes)
|
||||
{
|
||||
register unsigned int i;
|
||||
register ffi_type **p_arg;
|
||||
register void **p_argv;
|
||||
unsigned int slot = FIRST_ARG_SLOT;
|
||||
char *dest_cpy;
|
||||
size_t len;
|
||||
|
||||
debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__, stack,
|
||||
ecif, bytes);
|
||||
|
||||
p_arg = ecif->cif->arg_types;
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = 0; i < ecif->cif->nargs; i++)
|
||||
{
|
||||
int type = (*p_arg)->type;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(SINT32 *)(stack - slot) = *(SINT8 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(UINT32 *)(stack - slot) = *(UINT8 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(SINT32 *)(stack - slot) = *(SINT16 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(UINT32 *)(stack - slot) = *(UINT16 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_POINTER:
|
||||
debug(3, "Storing UINT32 %u in slot %u\n", *(UINT32 *)(*p_argv),
|
||||
slot);
|
||||
*(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
/* Align slot for 64-bit type. */
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
*(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
/* First 4 args go in fr4L - fr7L. */
|
||||
debug(3, "Storing UINT32(float) in slot %u\n", slot);
|
||||
*(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
|
||||
switch (slot - FIRST_ARG_SLOT)
|
||||
{
|
||||
/* First 4 args go in fr4L - fr7L. */
|
||||
case 0: fldw(stack - slot, fr4); break;
|
||||
case 1: fldw(stack - slot, fr5); break;
|
||||
case 2: fldw(stack - slot, fr6); break;
|
||||
case 3: fldw(stack - slot, fr7); break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
/* Align slot for 64-bit type. */
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
debug(3, "Storing UINT64(double) at slot %u\n", slot);
|
||||
*(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
|
||||
switch (slot - FIRST_ARG_SLOT)
|
||||
{
|
||||
/* First 2 args go in fr5, fr7. */
|
||||
case 1: fldd(stack - slot, fr5); break;
|
||||
case 3: fldd(stack - slot, fr7); break;
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef PA_HPUX
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* Long doubles are passed in the same manner as structures
|
||||
larger than 8 bytes. */
|
||||
*(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
|
||||
/* Structs smaller or equal than 4 bytes are passed in one
|
||||
register. Structs smaller or equal 8 bytes are passed in two
|
||||
registers. Larger structures are passed by pointer. */
|
||||
|
||||
len = (*p_arg)->size;
|
||||
if (len <= 4)
|
||||
{
|
||||
dest_cpy = (char *)(stack - slot) + 4 - len;
|
||||
memcpy(dest_cpy, (char *)*p_argv, len);
|
||||
}
|
||||
else if (len <= 8)
|
||||
{
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
dest_cpy = (char *)(stack - slot) + 8 - len;
|
||||
memcpy(dest_cpy, (char *)*p_argv, len);
|
||||
}
|
||||
else
|
||||
*(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
|
||||
slot++;
|
||||
p_arg++;
|
||||
p_argv++;
|
||||
}
|
||||
|
||||
/* Make sure we didn't mess up and scribble on the stack. */
|
||||
{
|
||||
unsigned int n;
|
||||
|
||||
debug(5, "Stack setup:\n");
|
||||
for (n = 0; n < (bytes + 3) / 4; n++)
|
||||
{
|
||||
if ((n%4) == 0) { debug(5, "\n%08x: ", (unsigned int)(stack - n)); }
|
||||
debug(5, "%08x ", *(stack - n));
|
||||
}
|
||||
debug(5, "\n");
|
||||
}
|
||||
|
||||
FFI_ASSERT(slot * 4 <= bytes);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void ffi_size_stack_pa32(ffi_cif *cif)
|
||||
{
|
||||
ffi_type **ptr;
|
||||
int i;
|
||||
int z = 0; /* # stack slots */
|
||||
|
||||
for (ptr = cif->arg_types, i = 0; i < cif->nargs; ptr++, i++)
|
||||
{
|
||||
int type = (*ptr)->type;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_DOUBLE:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
z += 2 + (z & 1); /* must start on even regs, so we may waste one */
|
||||
break;
|
||||
|
||||
#ifdef PA_HPUX
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
#endif
|
||||
case FFI_TYPE_STRUCT:
|
||||
z += 1; /* pass by ptr, callee will copy */
|
||||
break;
|
||||
|
||||
default: /* <= 32-bit values */
|
||||
z++;
|
||||
}
|
||||
}
|
||||
|
||||
/* We can fit up to 6 args in the default 64-byte stack frame,
|
||||
if we need more, we need more stack. */
|
||||
if (z <= 6)
|
||||
cif->bytes = MIN_STACK_SIZE; /* min stack size */
|
||||
else
|
||||
cif->bytes = 64 + ROUND_UP((z - 6) * sizeof(UINT32), MIN_STACK_SIZE);
|
||||
|
||||
debug(3, "Calculated stack size is %u bytes\n", cif->bytes);
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing. */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
|
||||
#ifdef PA_HPUX
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* Long doubles are treated like a structure. */
|
||||
cif->flags = FFI_TYPE_STRUCT;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* For the return type we have to check the size of the structures.
|
||||
If the size is smaller or equal 4 bytes, the result is given back
|
||||
in one register. If the size is smaller or equal 8 bytes than we
|
||||
return the result in two registers. But if the size is bigger than
|
||||
8 bytes, we work with pointers. */
|
||||
cif->flags = ffi_struct_type(cif->rtype);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
cif->flags = FFI_TYPE_UINT64;
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Lucky us, because of the unique PA ABI we get to do our
|
||||
own stack sizing. */
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_PA32:
|
||||
ffi_size_stack_pa32(cif);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern void ffi_call_pa32(void (*)(UINT32 *, extended_cif *, unsigned),
|
||||
extended_cif *, unsigned, unsigned, unsigned *,
|
||||
void (*fn)(void));
|
||||
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(void), 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
|
||||
#ifdef PA_HPUX
|
||||
&& (cif->rtype->type == FFI_TYPE_STRUCT
|
||||
|| cif->rtype->type == FFI_TYPE_LONGDOUBLE))
|
||||
#else
|
||||
&& cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
#endif
|
||||
{
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_PA32:
|
||||
debug(3, "Calling ffi_call_pa32: ecif=%p, bytes=%u, flags=%u, rvalue=%p, fn=%p\n", &ecif, cif->bytes, cif->flags, ecif.rvalue, (void *)fn);
|
||||
ffi_call_pa32(ffi_prep_args_pa32, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if FFI_CLOSURES
|
||||
/* This is more-or-less an inverse of ffi_call -- we have arguments on
|
||||
the stack, and we need to fill them into a cif structure and invoke
|
||||
the user function. This really ought to be in asm to make sure
|
||||
the compiler doesn't do things we don't expect. */
|
||||
ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
void **avalue;
|
||||
void *rvalue;
|
||||
UINT32 ret[2]; /* function can return up to 64-bits in registers */
|
||||
ffi_type **p_arg;
|
||||
char *tmp;
|
||||
int i, avn;
|
||||
unsigned int slot = FIRST_ARG_SLOT;
|
||||
register UINT32 r28 asm("r28");
|
||||
|
||||
cif = closure->cif;
|
||||
|
||||
/* If returning via structure, callee will write to our pointer. */
|
||||
if (cif->flags == FFI_TYPE_STRUCT)
|
||||
rvalue = (void *)r28;
|
||||
else
|
||||
rvalue = &ret[0];
|
||||
|
||||
avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG);
|
||||
avn = cif->nargs;
|
||||
p_arg = cif->arg_types;
|
||||
|
||||
for (i = 0; i < avn; i++)
|
||||
{
|
||||
int type = (*p_arg)->type;
|
||||
|
||||
switch (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_POINTER:
|
||||
avalue[i] = (char *)(stack - slot) + sizeof(UINT32) - (*p_arg)->size;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
avalue[i] = (void *)(stack - slot);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
#ifdef PA_LINUX
|
||||
/* The closure call is indirect. In Linux, floating point
|
||||
arguments in indirect calls with a prototype are passed
|
||||
in the floating point registers instead of the general
|
||||
registers. So, we need to replace what was previously
|
||||
stored in the current slot with the value in the
|
||||
corresponding floating point register. */
|
||||
switch (slot - FIRST_ARG_SLOT)
|
||||
{
|
||||
case 0: fstw(fr4, (void *)(stack - slot)); break;
|
||||
case 1: fstw(fr5, (void *)(stack - slot)); break;
|
||||
case 2: fstw(fr6, (void *)(stack - slot)); break;
|
||||
case 3: fstw(fr7, (void *)(stack - slot)); break;
|
||||
}
|
||||
#endif
|
||||
avalue[i] = (void *)(stack - slot);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
#ifdef PA_LINUX
|
||||
/* See previous comment for FFI_TYPE_FLOAT. */
|
||||
switch (slot - FIRST_ARG_SLOT)
|
||||
{
|
||||
case 1: fstd(fr5, (void *)(stack - slot)); break;
|
||||
case 3: fstd(fr7, (void *)(stack - slot)); break;
|
||||
}
|
||||
#endif
|
||||
avalue[i] = (void *)(stack - slot);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* Structs smaller or equal than 4 bytes are passed in one
|
||||
register. Structs smaller or equal 8 bytes are passed in two
|
||||
registers. Larger structures are passed by pointer. */
|
||||
if((*p_arg)->size <= 4)
|
||||
{
|
||||
avalue[i] = (void *)(stack - slot) + sizeof(UINT32) -
|
||||
(*p_arg)->size;
|
||||
}
|
||||
else if ((*p_arg)->size <= 8)
|
||||
{
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
avalue[i] = (void *)(stack - slot) + sizeof(UINT64) -
|
||||
(*p_arg)->size;
|
||||
}
|
||||
else
|
||||
avalue[i] = (void *) *(stack - slot);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
|
||||
slot++;
|
||||
p_arg++;
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0],
|
||||
ret[1]);
|
||||
|
||||
/* Store the result using the lower 2 bytes of the flags. */
|
||||
switch (cif->flags)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
*(stack - FIRST_ARG_SLOT) = (UINT8)(ret[0] >> 24);
|
||||
break;
|
||||
case FFI_TYPE_SINT8:
|
||||
*(stack - FIRST_ARG_SLOT) = (SINT8)(ret[0] >> 24);
|
||||
break;
|
||||
case FFI_TYPE_UINT16:
|
||||
*(stack - FIRST_ARG_SLOT) = (UINT16)(ret[0] >> 16);
|
||||
break;
|
||||
case FFI_TYPE_SINT16:
|
||||
*(stack - FIRST_ARG_SLOT) = (SINT16)(ret[0] >> 16);
|
||||
break;
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
*(stack - FIRST_ARG_SLOT) = ret[0];
|
||||
break;
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
*(stack - FIRST_ARG_SLOT) = ret[0];
|
||||
*(stack - FIRST_ARG_SLOT - 1) = ret[1];
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
fldd(rvalue, fr4);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
fldw(rvalue, fr4);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* Don't need a return value, done by caller. */
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SMALL_STRUCT2:
|
||||
case FFI_TYPE_SMALL_STRUCT3:
|
||||
case FFI_TYPE_SMALL_STRUCT4:
|
||||
tmp = (void*)(stack - FIRST_ARG_SLOT);
|
||||
tmp += 4 - cif->rtype->size;
|
||||
memcpy((void*)tmp, &ret[0], cif->rtype->size);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SMALL_STRUCT5:
|
||||
case FFI_TYPE_SMALL_STRUCT6:
|
||||
case FFI_TYPE_SMALL_STRUCT7:
|
||||
case FFI_TYPE_SMALL_STRUCT8:
|
||||
{
|
||||
unsigned int ret2[2];
|
||||
int off;
|
||||
|
||||
/* Right justify ret[0] and ret[1] */
|
||||
switch (cif->flags)
|
||||
{
|
||||
case FFI_TYPE_SMALL_STRUCT5: off = 3; break;
|
||||
case FFI_TYPE_SMALL_STRUCT6: off = 2; break;
|
||||
case FFI_TYPE_SMALL_STRUCT7: off = 1; break;
|
||||
default: off = 0; break;
|
||||
}
|
||||
|
||||
memset (ret2, 0, sizeof (ret2));
|
||||
memcpy ((char *)ret2 + off, ret, 8 - off);
|
||||
|
||||
*(stack - FIRST_ARG_SLOT) = ret2[0];
|
||||
*(stack - FIRST_ARG_SLOT - 1) = ret2[1];
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
case FFI_TYPE_VOID:
|
||||
break;
|
||||
|
||||
default:
|
||||
debug(0, "assert with cif->flags: %d\n",cif->flags);
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/* Fill in a closure to refer to the specified fun and user_data.
|
||||
cif specifies the argument and result types for fun.
|
||||
The cif must already be prep'ed. */
|
||||
|
||||
extern void ffi_closure_pa32(void);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
UINT32 *tramp = (UINT32 *)(closure->tramp);
|
||||
#ifdef PA_HPUX
|
||||
UINT32 *tmp;
|
||||
#endif
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_PA32);
|
||||
|
||||
/* Make a small trampoline that will branch to our
|
||||
handler function. Use PC-relative addressing. */
|
||||
|
||||
#ifdef PA_LINUX
|
||||
tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */
|
||||
tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */
|
||||
tramp[2] = 0x4aa10028; /* ldw 20(%r21),%r1 ; load plabel */
|
||||
tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */
|
||||
tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */
|
||||
tramp[5] = 0xeac0c000; /* bv%r0(%r22) ; branch to handler */
|
||||
tramp[6] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */
|
||||
tramp[7] = ((UINT32)(ffi_closure_pa32) & ~2);
|
||||
|
||||
/* Flush d/icache -- have to flush up 2 two lines because of
|
||||
alignment. */
|
||||
__asm__ volatile(
|
||||
"fdc 0(%0)\n\t"
|
||||
"fdc %1(%0)\n\t"
|
||||
"fic 0(%%sr4, %0)\n\t"
|
||||
"fic %1(%%sr4, %0)\n\t"
|
||||
"sync\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n"
|
||||
:
|
||||
: "r"((unsigned long)tramp & ~31),
|
||||
"r"(32 /* stride */)
|
||||
: "memory");
|
||||
#endif
|
||||
|
||||
#ifdef PA_HPUX
|
||||
tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */
|
||||
tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */
|
||||
tramp[2] = 0x4aa10038; /* ldw 28(%r21),%r1 ; load plabel */
|
||||
tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */
|
||||
tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */
|
||||
tramp[5] = 0x02c010b4; /* ldsid (%r22),%r20 ; load space id */
|
||||
tramp[6] = 0x00141820; /* mtsp %r20,%sr0 ; into %sr0 */
|
||||
tramp[7] = 0xe2c00000; /* be 0(%sr0,%r22) ; branch to handler */
|
||||
tramp[8] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */
|
||||
tramp[9] = ((UINT32)(ffi_closure_pa32) & ~2);
|
||||
|
||||
/* Flush d/icache -- have to flush three lines because of alignment. */
|
||||
__asm__ volatile(
|
||||
"copy %1,%0\n\t"
|
||||
"fdc,m %2(%0)\n\t"
|
||||
"fdc,m %2(%0)\n\t"
|
||||
"fdc,m %2(%0)\n\t"
|
||||
"ldsid (%1),%0\n\t"
|
||||
"mtsp %0,%%sr0\n\t"
|
||||
"copy %1,%0\n\t"
|
||||
"fic,m %2(%%sr0,%0)\n\t"
|
||||
"fic,m %2(%%sr0,%0)\n\t"
|
||||
"fic,m %2(%%sr0,%0)\n\t"
|
||||
"sync\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n"
|
||||
: "=&r" ((unsigned long)tmp)
|
||||
: "r" ((unsigned long)tramp & ~31),
|
||||
"r" (32/* stride */)
|
||||
: "memory");
|
||||
#endif
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
#endif
|
||||
77
src/pa/ffitarget.h
Normal file
77
src/pa/ffitarget.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for hppa.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
/* ---- System specific configurations ----------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
|
||||
#ifdef PA_LINUX
|
||||
FFI_PA32,
|
||||
FFI_DEFAULT_ABI = FFI_PA32,
|
||||
#endif
|
||||
|
||||
#ifdef PA_HPUX
|
||||
FFI_PA32,
|
||||
FFI_DEFAULT_ABI = FFI_PA32,
|
||||
#endif
|
||||
|
||||
#ifdef PA64_HPUX
|
||||
#error "PA64_HPUX FFI is not yet implemented"
|
||||
FFI_PA64,
|
||||
FFI_DEFAULT_ABI = FFI_PA64,
|
||||
#endif
|
||||
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#ifdef PA_LINUX
|
||||
#define FFI_TRAMPOLINE_SIZE 32
|
||||
#else
|
||||
#define FFI_TRAMPOLINE_SIZE 40
|
||||
#endif
|
||||
|
||||
#define FFI_TYPE_SMALL_STRUCT2 -1
|
||||
#define FFI_TYPE_SMALL_STRUCT3 -2
|
||||
#define FFI_TYPE_SMALL_STRUCT4 -3
|
||||
#define FFI_TYPE_SMALL_STRUCT5 -4
|
||||
#define FFI_TYPE_SMALL_STRUCT6 -5
|
||||
#define FFI_TYPE_SMALL_STRUCT7 -6
|
||||
#define FFI_TYPE_SMALL_STRUCT8 -7
|
||||
#endif
|
||||
368
src/pa/hpux32.S
Normal file
368
src/pa/hpux32.S
Normal file
@@ -0,0 +1,368 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
hpux32.S - Copyright (c) 2006 Free Software Foundation, Inc.
|
||||
(c) 2008 Red Hat, Inc.
|
||||
based on src/pa/linux.S
|
||||
|
||||
HP-UX PA 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
.LEVEL 1.1
|
||||
.SPACE $PRIVATE$
|
||||
.IMPORT $global$,DATA
|
||||
.IMPORT $$dyncall,MILLICODE
|
||||
.SUBSPA $DATA$
|
||||
.align 4
|
||||
|
||||
/* void ffi_call_pa32(void (*)(char *, extended_cif *),
|
||||
extended_cif *ecif,
|
||||
unsigned bytes,
|
||||
unsigned flags,
|
||||
unsigned *rvalue,
|
||||
void (*fn)(void));
|
||||
*/
|
||||
|
||||
.export ffi_call_pa32,ENTRY,PRIV_LEV=3
|
||||
.import ffi_prep_args_pa32,CODE
|
||||
|
||||
.SPACE $TEXT$
|
||||
.SUBSPA $CODE$
|
||||
.align 4
|
||||
|
||||
L$FB1
|
||||
ffi_call_pa32
|
||||
.proc
|
||||
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
|
||||
.entry
|
||||
stw %rp, -20(%sp)
|
||||
copy %r3, %r1
|
||||
L$CFI11
|
||||
copy %sp, %r3
|
||||
L$CFI12
|
||||
|
||||
/* Setup the stack for calling prep_args...
|
||||
We want the stack to look like this:
|
||||
|
||||
[ Previous stack ] <- %r3
|
||||
|
||||
[ 64-bytes register save area ] <- %r4
|
||||
|
||||
[ Stack space for actual call, passed as ] <- %arg0
|
||||
[ arg0 to ffi_prep_args_pa32 ]
|
||||
|
||||
[ Stack for calling prep_args ] <- %sp
|
||||
*/
|
||||
|
||||
stwm %r1, 64(%sp)
|
||||
stw %r4, 12(%r3)
|
||||
L$CFI13
|
||||
copy %sp, %r4
|
||||
|
||||
addl %arg2, %r4, %arg0 ; arg stack
|
||||
stw %arg3, -48(%r3) ; save flags we need it later
|
||||
|
||||
/* Call prep_args:
|
||||
%arg0(stack) -- set up above
|
||||
%arg1(ecif) -- same as incoming param
|
||||
%arg2(bytes) -- same as incoming param */
|
||||
bl ffi_prep_args_pa32,%r2
|
||||
ldo 64(%arg0), %sp
|
||||
ldo -64(%sp), %sp
|
||||
|
||||
/* now %sp should point where %arg0 was pointing. */
|
||||
|
||||
/* Load the arguments that should be passed in registers
|
||||
The fp args are loaded by the prep_args function. */
|
||||
ldw -36(%sp), %arg0
|
||||
ldw -40(%sp), %arg1
|
||||
ldw -44(%sp), %arg2
|
||||
ldw -48(%sp), %arg3
|
||||
|
||||
/* in case the function is going to return a structure
|
||||
we need to give it a place to put the result. */
|
||||
ldw -52(%r3), %ret0 ; %ret0 <- rvalue
|
||||
ldw -56(%r3), %r22 ; %r22 <- function to call
|
||||
bl $$dyncall, %r31 ; Call the user function
|
||||
copy %r31, %rp
|
||||
|
||||
/* Prepare to store the result; we need to recover flags and rvalue. */
|
||||
ldw -48(%r3), %r21 ; r21 <- flags
|
||||
ldw -52(%r3), %r20 ; r20 <- rvalue
|
||||
|
||||
/* Store the result according to the return type. The most
|
||||
likely types should come first. */
|
||||
|
||||
L$checkint
|
||||
comib,<>,n FFI_TYPE_INT, %r21, L$checkint8
|
||||
b L$done
|
||||
stw %ret0, 0(%r20)
|
||||
|
||||
L$checkint8
|
||||
comib,<>,n FFI_TYPE_UINT8, %r21, L$checkint16
|
||||
b L$done
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
L$checkint16
|
||||
comib,<>,n FFI_TYPE_UINT16, %r21, L$checkdbl
|
||||
b L$done
|
||||
sth %ret0, 0(%r20)
|
||||
|
||||
L$checkdbl
|
||||
comib,<>,n FFI_TYPE_DOUBLE, %r21, L$checkfloat
|
||||
b L$done
|
||||
fstd %fr4,0(%r20)
|
||||
|
||||
L$checkfloat
|
||||
comib,<>,n FFI_TYPE_FLOAT, %r21, L$checkll
|
||||
b L$done
|
||||
fstw %fr4L,0(%r20)
|
||||
|
||||
L$checkll
|
||||
comib,<>,n FFI_TYPE_UINT64, %r21, L$checksmst2
|
||||
stw %ret0, 0(%r20)
|
||||
b L$done
|
||||
stw %ret1, 4(%r20)
|
||||
|
||||
L$checksmst2
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, L$checksmst3
|
||||
/* 2-byte structs are returned in ret0 as ????xxyy. */
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b L$done
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
L$checksmst3
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, L$checksmst4
|
||||
/* 3-byte structs are returned in ret0 as ??xxyyzz. */
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b L$done
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
L$checksmst4
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT4, %r21, L$checksmst5
|
||||
/* 4-byte structs are returned in ret0 as wwxxyyzz. */
|
||||
extru %ret0, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b L$done
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
L$checksmst5
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT5, %r21, L$checksmst6
|
||||
/* 5 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
5: ??????aa bbccddee */
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b L$done
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
L$checksmst6
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT6, %r21, L$checksmst7
|
||||
/* 6 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
6: ????aabb ccddeeff */
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b L$done
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
L$checksmst7
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT7, %r21, L$checksmst8
|
||||
/* 7 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
7: ??aabbcc ddeeffgg */
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b L$done
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
L$checksmst8
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT8, %r21, L$done
|
||||
/* 8 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
8: aabbccdd eeffgghh */
|
||||
extru %ret0, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
L$done
|
||||
/* all done, return */
|
||||
copy %r4, %sp ; pop arg stack
|
||||
ldw 12(%r3), %r4
|
||||
ldwm -64(%sp), %r3 ; .. and pop stack
|
||||
ldw -20(%sp), %rp
|
||||
bv %r0(%rp)
|
||||
nop
|
||||
.exit
|
||||
.procend
|
||||
L$FE1
|
||||
|
||||
/* void ffi_closure_pa32(void);
|
||||
Called with closure argument in %r21 */
|
||||
|
||||
.SPACE $TEXT$
|
||||
.SUBSPA $CODE$
|
||||
.export ffi_closure_pa32,ENTRY,PRIV_LEV=3,RTNVAL=GR
|
||||
.import ffi_closure_inner_pa32,CODE
|
||||
.align 4
|
||||
L$FB2
|
||||
ffi_closure_pa32
|
||||
.proc
|
||||
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
|
||||
.entry
|
||||
|
||||
stw %rp, -20(%sp)
|
||||
copy %r3, %r1
|
||||
L$CFI21
|
||||
copy %sp, %r3
|
||||
L$CFI22
|
||||
stwm %r1, 64(%sp)
|
||||
|
||||
/* Put arguments onto the stack and call ffi_closure_inner. */
|
||||
stw %arg0, -36(%r3)
|
||||
stw %arg1, -40(%r3)
|
||||
stw %arg2, -44(%r3)
|
||||
stw %arg3, -48(%r3)
|
||||
|
||||
copy %r21, %arg0
|
||||
bl ffi_closure_inner_pa32, %r2
|
||||
copy %r3, %arg1
|
||||
ldwm -64(%sp), %r3
|
||||
ldw -20(%sp), %rp
|
||||
ldw -36(%sp), %ret0
|
||||
bv %r0(%rp)
|
||||
ldw -40(%sp), %ret1
|
||||
.exit
|
||||
.procend
|
||||
L$FE2:
|
||||
|
||||
.SPACE $PRIVATE$
|
||||
.SUBSPA $DATA$
|
||||
|
||||
.align 4
|
||||
.EXPORT _GLOBAL__F_ffi_call_pa32,DATA
|
||||
_GLOBAL__F_ffi_call_pa32
|
||||
L$frame1:
|
||||
.word L$ECIE1-L$SCIE1 ;# Length of Common Information Entry
|
||||
L$SCIE1:
|
||||
.word 0x0 ;# CIE Identifier Tag
|
||||
.byte 0x1 ;# CIE Version
|
||||
.ascii "\0" ;# CIE Augmentation
|
||||
.uleb128 0x1 ;# CIE Code Alignment Factor
|
||||
.sleb128 4 ;# CIE Data Alignment Factor
|
||||
.byte 0x2 ;# CIE RA Column
|
||||
.byte 0xc ;# DW_CFA_def_cfa
|
||||
.uleb128 0x1e
|
||||
.uleb128 0x0
|
||||
.align 4
|
||||
L$ECIE1:
|
||||
L$SFDE1:
|
||||
.word L$EFDE1-L$ASFDE1 ;# FDE Length
|
||||
L$ASFDE1:
|
||||
.word L$ASFDE1-L$frame1 ;# FDE CIE offset
|
||||
.word L$FB1 ;# FDE initial location
|
||||
.word L$FE1-L$FB1 ;# FDE address range
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word L$CFI11-L$FB1
|
||||
.byte 0x83 ;# DW_CFA_offset, column 0x3
|
||||
.uleb128 0x0
|
||||
.byte 0x11 ;# DW_CFA_offset_extended_sf; save r2 at [r30-20]
|
||||
.uleb128 0x2
|
||||
.sleb128 -5
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word L$CFI12-L$CFI11
|
||||
.byte 0xd ;# DW_CFA_def_cfa_register = r3
|
||||
.uleb128 0x3
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word L$CFI13-L$CFI12
|
||||
.byte 0x84 ;# DW_CFA_offset, column 0x4
|
||||
.uleb128 0x3
|
||||
|
||||
.align 4
|
||||
L$EFDE1:
|
||||
|
||||
L$SFDE2:
|
||||
.word L$EFDE2-L$ASFDE2 ;# FDE Length
|
||||
L$ASFDE2:
|
||||
.word L$ASFDE2-L$frame1 ;# FDE CIE offset
|
||||
.word L$FB2 ;# FDE initial location
|
||||
.word L$FE2-L$FB2 ;# FDE address range
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word L$CFI21-L$FB2
|
||||
.byte 0x83 ;# DW_CFA_offset, column 0x3
|
||||
.uleb128 0x0
|
||||
.byte 0x11 ;# DW_CFA_offset_extended_sf
|
||||
.uleb128 0x2
|
||||
.sleb128 -5
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word L$CFI22-L$CFI21
|
||||
.byte 0xd ;# DW_CFA_def_cfa_register = r3
|
||||
.uleb128 0x3
|
||||
|
||||
.align 4
|
||||
L$EFDE2:
|
||||
357
src/pa/linux.S
Normal file
357
src/pa/linux.S
Normal file
@@ -0,0 +1,357 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
linux.S - (c) 2003-2004 Randolph Chung <tausq@debian.org>
|
||||
(c) 2008 Red Hat, Inc.
|
||||
|
||||
HPPA 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 RENESAS TECHNOLOGY 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
.text
|
||||
.level 1.1
|
||||
.align 4
|
||||
|
||||
/* void ffi_call_pa32(void (*)(char *, extended_cif *),
|
||||
extended_cif *ecif,
|
||||
unsigned bytes,
|
||||
unsigned flags,
|
||||
unsigned *rvalue,
|
||||
void (*fn)(void));
|
||||
*/
|
||||
|
||||
.export ffi_call_pa32,code
|
||||
.import ffi_prep_args_pa32,code
|
||||
|
||||
.type ffi_call_pa32, @function
|
||||
.LFB1:
|
||||
ffi_call_pa32:
|
||||
.proc
|
||||
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
|
||||
.entry
|
||||
stw %rp, -20(%sp)
|
||||
copy %r3, %r1
|
||||
.LCFI11:
|
||||
|
||||
copy %sp, %r3
|
||||
.LCFI12:
|
||||
|
||||
/* Setup the stack for calling prep_args...
|
||||
We want the stack to look like this:
|
||||
|
||||
[ Previous stack ] <- %r3
|
||||
|
||||
[ 64-bytes register save area ] <- %r4
|
||||
|
||||
[ Stack space for actual call, passed as ] <- %arg0
|
||||
[ arg0 to ffi_prep_args_pa32 ]
|
||||
|
||||
[ Stack for calling prep_args ] <- %sp
|
||||
*/
|
||||
|
||||
stwm %r1, 64(%sp)
|
||||
stw %r4, 12(%r3)
|
||||
.LCFI13:
|
||||
copy %sp, %r4
|
||||
|
||||
addl %arg2, %r4, %arg0 /* arg stack */
|
||||
stw %arg3, -48(%r3) /* save flags; we need it later */
|
||||
|
||||
/* Call prep_args:
|
||||
%arg0(stack) -- set up above
|
||||
%arg1(ecif) -- same as incoming param
|
||||
%arg2(bytes) -- same as incoming param */
|
||||
bl ffi_prep_args_pa32,%r2
|
||||
ldo 64(%arg0), %sp
|
||||
ldo -64(%sp), %sp
|
||||
|
||||
/* now %sp should point where %arg0 was pointing. */
|
||||
|
||||
/* Load the arguments that should be passed in registers
|
||||
The fp args were loaded by the prep_args function. */
|
||||
ldw -36(%sp), %arg0
|
||||
ldw -40(%sp), %arg1
|
||||
ldw -44(%sp), %arg2
|
||||
ldw -48(%sp), %arg3
|
||||
|
||||
/* in case the function is going to return a structure
|
||||
we need to give it a place to put the result. */
|
||||
ldw -52(%r3), %ret0 /* %ret0 <- rvalue */
|
||||
ldw -56(%r3), %r22 /* %r22 <- function to call */
|
||||
bl $$dyncall, %r31 /* Call the user function */
|
||||
copy %r31, %rp
|
||||
|
||||
/* Prepare to store the result; we need to recover flags and rvalue. */
|
||||
ldw -48(%r3), %r21 /* r21 <- flags */
|
||||
ldw -52(%r3), %r20 /* r20 <- rvalue */
|
||||
|
||||
/* Store the result according to the return type. */
|
||||
|
||||
.Lcheckint:
|
||||
comib,<>,n FFI_TYPE_INT, %r21, .Lcheckint8
|
||||
b .Ldone
|
||||
stw %ret0, 0(%r20)
|
||||
|
||||
.Lcheckint8:
|
||||
comib,<>,n FFI_TYPE_UINT8, %r21, .Lcheckint16
|
||||
b .Ldone
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
.Lcheckint16:
|
||||
comib,<>,n FFI_TYPE_UINT16, %r21, .Lcheckdbl
|
||||
b .Ldone
|
||||
sth %ret0, 0(%r20)
|
||||
|
||||
.Lcheckdbl:
|
||||
comib,<>,n FFI_TYPE_DOUBLE, %r21, .Lcheckfloat
|
||||
b .Ldone
|
||||
fstd %fr4,0(%r20)
|
||||
|
||||
.Lcheckfloat:
|
||||
comib,<>,n FFI_TYPE_FLOAT, %r21, .Lcheckll
|
||||
b .Ldone
|
||||
fstw %fr4L,0(%r20)
|
||||
|
||||
.Lcheckll:
|
||||
comib,<>,n FFI_TYPE_UINT64, %r21, .Lchecksmst2
|
||||
stw %ret0, 0(%r20)
|
||||
b .Ldone
|
||||
stw %ret1, 4(%r20)
|
||||
|
||||
.Lchecksmst2:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, .Lchecksmst3
|
||||
/* 2-byte structs are returned in ret0 as ????xxyy. */
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
.Lchecksmst3:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, .Lchecksmst4
|
||||
/* 3-byte structs are returned in ret0 as ??xxyyzz. */
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
.Lchecksmst4:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT4, %r21, .Lchecksmst5
|
||||
/* 4-byte structs are returned in ret0 as wwxxyyzz. */
|
||||
extru %ret0, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
.Lchecksmst5:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT5, %r21, .Lchecksmst6
|
||||
/* 5 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
5: ??????aa bbccddee */
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
.Lchecksmst6:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT6, %r21, .Lchecksmst7
|
||||
/* 6 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
6: ????aabb ccddeeff */
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
.Lchecksmst7:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT7, %r21, .Lchecksmst8
|
||||
/* 7 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
7: ??aabbcc ddeeffgg */
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
.Lchecksmst8:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT8, %r21, .Ldone
|
||||
/* 8 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
8: aabbccdd eeffgghh */
|
||||
extru %ret0, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
.Ldone:
|
||||
/* all done, return */
|
||||
copy %r4, %sp /* pop arg stack */
|
||||
ldw 12(%r3), %r4
|
||||
ldwm -64(%sp), %r3 /* .. and pop stack */
|
||||
ldw -20(%sp), %rp
|
||||
bv %r0(%rp)
|
||||
nop
|
||||
.exit
|
||||
.procend
|
||||
.LFE1:
|
||||
|
||||
/* void ffi_closure_pa32(void);
|
||||
Called with closure argument in %r21 */
|
||||
.export ffi_closure_pa32,code
|
||||
.import ffi_closure_inner_pa32,code
|
||||
|
||||
.type ffi_closure_pa32, @function
|
||||
.LFB2:
|
||||
ffi_closure_pa32:
|
||||
.proc
|
||||
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
|
||||
.entry
|
||||
|
||||
stw %rp, -20(%sp)
|
||||
.LCFI20:
|
||||
copy %r3, %r1
|
||||
.LCFI21:
|
||||
copy %sp, %r3
|
||||
.LCFI22:
|
||||
stwm %r1, 64(%sp)
|
||||
|
||||
/* Put arguments onto the stack and call ffi_closure_inner. */
|
||||
stw %arg0, -36(%r3)
|
||||
stw %arg1, -40(%r3)
|
||||
stw %arg2, -44(%r3)
|
||||
stw %arg3, -48(%r3)
|
||||
|
||||
copy %r21, %arg0
|
||||
bl ffi_closure_inner_pa32, %r2
|
||||
copy %r3, %arg1
|
||||
|
||||
ldwm -64(%sp), %r3
|
||||
ldw -20(%sp), %rp
|
||||
ldw -36(%sp), %ret0
|
||||
bv %r0(%r2)
|
||||
ldw -40(%sp), %ret1
|
||||
|
||||
.exit
|
||||
.procend
|
||||
.LFE2:
|
||||
|
||||
.section ".eh_frame",EH_FRAME_FLAGS,@progbits
|
||||
.Lframe1:
|
||||
.word .LECIE1-.LSCIE1 ;# Length of Common Information Entry
|
||||
.LSCIE1:
|
||||
.word 0x0 ;# CIE Identifier Tag
|
||||
.byte 0x1 ;# CIE Version
|
||||
.ascii "\0" ;# CIE Augmentation
|
||||
.uleb128 0x1 ;# CIE Code Alignment Factor
|
||||
.sleb128 4 ;# CIE Data Alignment Factor
|
||||
.byte 0x2 ;# CIE RA Column
|
||||
.byte 0xc ;# DW_CFA_def_cfa
|
||||
.uleb128 0x1e
|
||||
.uleb128 0x0
|
||||
.align 4
|
||||
.LECIE1:
|
||||
.LSFDE1:
|
||||
.word .LEFDE1-.LASFDE1 ;# FDE Length
|
||||
.LASFDE1:
|
||||
.word .LASFDE1-.Lframe1 ;# FDE CIE offset
|
||||
.word .LFB1 ;# FDE initial location
|
||||
.word .LFE1-.LFB1 ;# FDE address range
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word .LCFI11-.LFB1
|
||||
.byte 0x83 ;# DW_CFA_offset, column 0x3
|
||||
.uleb128 0x0
|
||||
.byte 0x11 ;# DW_CFA_offset_extended_sf; save r2 at [r30-20]
|
||||
.uleb128 0x2
|
||||
.sleb128 -5
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word .LCFI12-.LCFI11
|
||||
.byte 0xd ;# DW_CFA_def_cfa_register = r3
|
||||
.uleb128 0x3
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word .LCFI13-.LCFI12
|
||||
.byte 0x84 ;# DW_CFA_offset, column 0x4
|
||||
.uleb128 0x3
|
||||
|
||||
.align 4
|
||||
.LEFDE1:
|
||||
|
||||
.LSFDE2:
|
||||
.word .LEFDE2-.LASFDE2 ;# FDE Length
|
||||
.LASFDE2:
|
||||
.word .LASFDE2-.Lframe1 ;# FDE CIE offset
|
||||
.word .LFB2 ;# FDE initial location
|
||||
.word .LFE2-.LFB2 ;# FDE address range
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word .LCFI21-.LFB2
|
||||
.byte 0x83 ;# DW_CFA_offset, column 0x3
|
||||
.uleb128 0x0
|
||||
.byte 0x11 ;# DW_CFA_offset_extended_sf
|
||||
.uleb128 0x2
|
||||
.sleb128 -5
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word .LCFI22-.LCFI21
|
||||
.byte 0xd ;# DW_CFA_def_cfa_register = r3
|
||||
.uleb128 0x3
|
||||
|
||||
.align 4
|
||||
.LEFDE2:
|
||||
436
src/powerpc/.svn/entries
Normal file
436
src/powerpc/.svn/entries
Normal file
@@ -0,0 +1,436 @@
|
||||
10
|
||||
|
||||
dir
|
||||
152280
|
||||
svn://gcc.gnu.org/svn/gcc/trunk/libffi/src/powerpc
|
||||
svn://gcc.gnu.org/svn/gcc
|
||||
|
||||
|
||||
|
||||
2009-06-16T17:55:39.375944Z
|
||||
148543
|
||||
andreast
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
138bc75d-0d04-0410-961f-82ee72b054a4
|
||||
|
||||
ppc_closure.S
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:00.000000Z
|
||||
688696f2414aa7866b7c92c8684718d4
|
||||
2009-06-04T15:43:03.499507Z
|
||||
148172
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
7130
|
||||
|
||||
darwin_closure.S
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-04-24T17:46:15.000000Z
|
||||
31cb78f1f10503180bd8dc1ea0076ad1
|
||||
2005-03-24T00:45:38.000000Z
|
||||
96967
|
||||
mrs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
7243
|
||||
|
||||
ffitarget.h
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:00.000000Z
|
||||
b12a0e2e6ad83a41d1e1dd9eecb4141f
|
||||
2009-06-04T15:11:12.475454Z
|
||||
148171
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
3517
|
||||
|
||||
aix.S
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-04-24T17:46:15.000000Z
|
||||
d23701ff3a05628dde1d8c18d2911662
|
||||
2004-09-02T21:07:21.000000Z
|
||||
86991
|
||||
andreast
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
4763
|
||||
|
||||
darwin.S
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-04-24T17:46:15.000000Z
|
||||
24ade1d97acb5fb9f4033f7266b5cede
|
||||
2005-03-24T00:45:38.000000Z
|
||||
96967
|
||||
mrs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
6104
|
||||
|
||||
ffi.c
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-20T15:53:35.000000Z
|
||||
5e33e72fe5ecabf0a89cf4d5227cb1ca
|
||||
2009-06-16T17:55:39.375944Z
|
||||
148543
|
||||
andreast
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
39006
|
||||
|
||||
sysv.S
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-20T15:53:35.000000Z
|
||||
53da07be3982ee6cf80c7938c77e8ef7
|
||||
2009-06-16T17:55:39.375944Z
|
||||
148543
|
||||
andreast
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
6572
|
||||
|
||||
asm.h
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-04-24T17:46:15.000000Z
|
||||
41549f68aeedd29e849159d4567ede07
|
||||
2004-09-02T21:07:21.000000Z
|
||||
86991
|
||||
andreast
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
4310
|
||||
|
||||
linux64_closure.S
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:00.000000Z
|
||||
6fcea235a139c24a1ce2f1648875b50e
|
||||
2009-06-04T15:43:03.499507Z
|
||||
148172
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
5891
|
||||
|
||||
ffi_darwin.c
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:00.000000Z
|
||||
99c864cc939078110592da3cedda290f
|
||||
2009-06-04T15:43:03.499507Z
|
||||
148172
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
23367
|
||||
|
||||
linux64.S
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:00.000000Z
|
||||
a7d09aad6ca2eb4358d7ad4bca4fdd7e
|
||||
2009-06-04T15:43:03.499507Z
|
||||
148172
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
4981
|
||||
|
||||
aix_closure.S
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-04-24T17:46:15.000000Z
|
||||
049e042e968b560f48689cfc881d2db6
|
||||
2004-09-02T21:07:21.000000Z
|
||||
86991
|
||||
andreast
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
5613
|
||||
|
||||
225
src/powerpc/.svn/text-base/aix.S.svn-base
Normal file
225
src/powerpc/.svn/text-base/aix.S.svn-base
Normal file
@@ -0,0 +1,225 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
aix.S - Copyright (c) 2002 Free Software Foundation, Inc.
|
||||
based on darwin.S by John Hornkvist
|
||||
|
||||
PowerPC 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
.set r0,0
|
||||
.set r1,1
|
||||
.set r2,2
|
||||
.set r3,3
|
||||
.set r4,4
|
||||
.set r5,5
|
||||
.set r6,6
|
||||
.set r7,7
|
||||
.set r8,8
|
||||
.set r9,9
|
||||
.set r10,10
|
||||
.set r11,11
|
||||
.set r12,12
|
||||
.set r13,13
|
||||
.set r14,14
|
||||
.set r15,15
|
||||
.set r16,16
|
||||
.set r17,17
|
||||
.set r18,18
|
||||
.set r19,19
|
||||
.set r20,20
|
||||
.set r21,21
|
||||
.set r22,22
|
||||
.set r23,23
|
||||
.set r24,24
|
||||
.set r25,25
|
||||
.set r26,26
|
||||
.set r27,27
|
||||
.set r28,28
|
||||
.set r29,29
|
||||
.set r30,30
|
||||
.set r31,31
|
||||
.set f0,0
|
||||
.set f1,1
|
||||
.set f2,2
|
||||
.set f3,3
|
||||
.set f4,4
|
||||
.set f5,5
|
||||
.set f6,6
|
||||
.set f7,7
|
||||
.set f8,8
|
||||
.set f9,9
|
||||
.set f10,10
|
||||
.set f11,11
|
||||
.set f12,12
|
||||
.set f13,13
|
||||
.set f14,14
|
||||
.set f15,15
|
||||
.set f16,16
|
||||
.set f17,17
|
||||
.set f18,18
|
||||
.set f19,19
|
||||
.set f20,20
|
||||
.set f21,21
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#define JUMPTARGET(name) name
|
||||
#define L(x) x
|
||||
.file "aix.S"
|
||||
.toc
|
||||
.csect .text[PR]
|
||||
.align 2
|
||||
.globl ffi_prep_args
|
||||
|
||||
.csect .text[PR]
|
||||
.align 2
|
||||
.globl ffi_call_AIX
|
||||
.globl .ffi_call_AIX
|
||||
.csect ffi_call_AIX[DS]
|
||||
ffi_call_AIX:
|
||||
.long .ffi_call_AIX, TOC[tc0], 0
|
||||
.csect .text[PR]
|
||||
.ffi_call_AIX:
|
||||
mr r12,r8 // We only need r12 until the call, so it doesn't have to be saved...
|
||||
/* Save the old stack pointer as AP. */
|
||||
mr r8,r1
|
||||
|
||||
/* Allocate the stack space we need. */
|
||||
stwux r1,r1,r4
|
||||
|
||||
/* Save registers we use. */
|
||||
mflr r9
|
||||
|
||||
stw r28,-16(r8)
|
||||
stw r29,-12(r8)
|
||||
stw r30, -8(r8)
|
||||
stw r31, -4(r8)
|
||||
|
||||
stw r9, 8(r8)
|
||||
stw r2, 20(r1)
|
||||
|
||||
/* Save arguments over call... */
|
||||
mr r31,r5 /* flags, */
|
||||
mr r30,r6 /* rvalue, */
|
||||
mr r29,r7 /* function address, */
|
||||
mr r28,r8 /* our AP. */
|
||||
|
||||
/* Call ffi_prep_args. */
|
||||
mr r4,r1
|
||||
li r9,0
|
||||
|
||||
lwz r2,4(r12)
|
||||
lwz r12,0(r12)
|
||||
mtctr r12 // r12 holds address of _ffi_prep_args
|
||||
bctrl
|
||||
lwz r2,20(r1)
|
||||
|
||||
/* Now do the call. */
|
||||
lwz r12,0(r29)
|
||||
/* Set up cr1 with bits 4-7 of the flags. */
|
||||
mtcrf 0x40,r31
|
||||
stw r2,20(r1)
|
||||
mtctr r12
|
||||
lwz r2,4(r29)
|
||||
/* Load all those argument registers. */
|
||||
// We have set up a nice stack frame, just load it into registers.
|
||||
lwz r3, 20+(1*4)(r1)
|
||||
lwz r4, 20+(2*4)(r1)
|
||||
lwz r5, 20+(3*4)(r1)
|
||||
lwz r6, 20+(4*4)(r1)
|
||||
nop
|
||||
lwz r7, 20+(5*4)(r1)
|
||||
lwz r8, 20+(6*4)(r1)
|
||||
lwz r9, 20+(7*4)(r1)
|
||||
lwz r10,20+(8*4)(r1)
|
||||
|
||||
L1:
|
||||
/* Load all the FP registers. */
|
||||
bf 6,L2 // 2f + 0x18
|
||||
lfd f1,-16-(13*8)(r28)
|
||||
lfd f2,-16-(12*8)(r28)
|
||||
lfd f3,-16-(11*8)(r28)
|
||||
lfd f4,-16-(10*8)(r28)
|
||||
nop
|
||||
lfd f5,-16-(9*8)(r28)
|
||||
lfd f6,-16-(8*8)(r28)
|
||||
lfd f7,-16-(7*8)(r28)
|
||||
lfd f8,-16-(6*8)(r28)
|
||||
nop
|
||||
lfd f9,-16-(5*8)(r28)
|
||||
lfd f10,-16-(4*8)(r28)
|
||||
lfd f11,-16-(3*8)(r28)
|
||||
lfd f12,-16-(2*8)(r28)
|
||||
nop
|
||||
lfd f13,-16-(1*8)(r28)
|
||||
|
||||
L2:
|
||||
/* Make the call. */
|
||||
bctrl
|
||||
lwz r2,20(r1)
|
||||
|
||||
/* Now, deal with the return value. */
|
||||
mtcrf 0x01,r31
|
||||
|
||||
bt 30,L(done_return_value)
|
||||
bt 29,L(fp_return_value)
|
||||
stw r3,0(r30)
|
||||
bf 28,L(done_return_value)
|
||||
stw r4,4(r30)
|
||||
|
||||
/* Fall through... */
|
||||
|
||||
L(done_return_value):
|
||||
/* Restore the registers we used and return. */
|
||||
lwz r9, 8(r28)
|
||||
lwz r31, -4(r28)
|
||||
mtlr r9
|
||||
lwz r30, -8(r28)
|
||||
lwz r29,-12(r28)
|
||||
lwz r28,-16(r28)
|
||||
lwz r1,0(r1)
|
||||
blr
|
||||
|
||||
L(fp_return_value):
|
||||
bf 28,L(float_return_value)
|
||||
stfd f1,0(r30)
|
||||
b L(done_return_value)
|
||||
L(float_return_value):
|
||||
stfs f1,0(r30)
|
||||
b L(done_return_value)
|
||||
.long 0
|
||||
.byte 0,0,0,1,128,4,0,0
|
||||
//END(ffi_call_AIX)
|
||||
|
||||
.csect .text[PR]
|
||||
.align 2
|
||||
.globl ffi_call_DARWIN
|
||||
.globl .ffi_call_DARWIN
|
||||
.csect ffi_call_DARWIN[DS]
|
||||
ffi_call_DARWIN:
|
||||
.long .ffi_call_DARWIN, TOC[tc0], 0
|
||||
.csect .text[PR]
|
||||
.ffi_call_DARWIN:
|
||||
blr
|
||||
.long 0
|
||||
.byte 0,0,0,0,0,0,0,0
|
||||
//END(ffi_call_DARWIN)
|
||||
247
src/powerpc/.svn/text-base/aix_closure.S.svn-base
Normal file
247
src/powerpc/.svn/text-base/aix_closure.S.svn-base
Normal file
@@ -0,0 +1,247 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
aix_closure.S - Copyright (c) 2002 2003 Free Software Foundation, Inc.
|
||||
based on darwin_closure.S
|
||||
|
||||
PowerPC 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
.set r0,0
|
||||
.set r1,1
|
||||
.set r2,2
|
||||
.set r3,3
|
||||
.set r4,4
|
||||
.set r5,5
|
||||
.set r6,6
|
||||
.set r7,7
|
||||
.set r8,8
|
||||
.set r9,9
|
||||
.set r10,10
|
||||
.set r11,11
|
||||
.set r12,12
|
||||
.set r13,13
|
||||
.set r14,14
|
||||
.set r15,15
|
||||
.set r16,16
|
||||
.set r17,17
|
||||
.set r18,18
|
||||
.set r19,19
|
||||
.set r20,20
|
||||
.set r21,21
|
||||
.set r22,22
|
||||
.set r23,23
|
||||
.set r24,24
|
||||
.set r25,25
|
||||
.set r26,26
|
||||
.set r27,27
|
||||
.set r28,28
|
||||
.set r29,29
|
||||
.set r30,30
|
||||
.set r31,31
|
||||
.set f0,0
|
||||
.set f1,1
|
||||
.set f2,2
|
||||
.set f3,3
|
||||
.set f4,4
|
||||
.set f5,5
|
||||
.set f6,6
|
||||
.set f7,7
|
||||
.set f8,8
|
||||
.set f9,9
|
||||
.set f10,10
|
||||
.set f11,11
|
||||
.set f12,12
|
||||
.set f13,13
|
||||
.set f14,14
|
||||
.set f15,15
|
||||
.set f16,16
|
||||
.set f17,17
|
||||
.set f18,18
|
||||
.set f19,19
|
||||
.set f20,20
|
||||
.set f21,21
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#define JUMPTARGET(name) name
|
||||
#define L(x) x
|
||||
.file "aix_closure.S"
|
||||
.toc
|
||||
LC..60:
|
||||
.tc L..60[TC],L..60
|
||||
.csect .text[PR]
|
||||
.align 2
|
||||
|
||||
.csect .text[PR]
|
||||
.align 2
|
||||
.globl ffi_closure_ASM
|
||||
.globl .ffi_closure_ASM
|
||||
.csect ffi_closure_ASM[DS]
|
||||
|
||||
ffi_closure_ASM:
|
||||
.long .ffi_closure_ASM, TOC[tc0], 0
|
||||
.csect .text[PR]
|
||||
.ffi_closure_ASM:
|
||||
|
||||
mflr r0 /* extract return address */
|
||||
stw r0, 8(r1) /* save the return address */
|
||||
|
||||
/* 24 Bytes (Linkage Area) */
|
||||
/* 32 Bytes (params) */
|
||||
/* 104 Bytes (13*8 from FPR) */
|
||||
/* 8 Bytes (result) */
|
||||
/* 168 Bytes */
|
||||
|
||||
stwu r1,-176(r1) /* skip over caller save area
|
||||
keep stack aligned to 16 */
|
||||
|
||||
/* we want to build up an area for the parameters passed */
|
||||
/* in registers (both floating point and integer) */
|
||||
|
||||
/* we store gpr 3 to gpr 10 (aligned to 4)
|
||||
in the parents outgoing area */
|
||||
stw r3, 200(r1)
|
||||
stw r4, 204(r1)
|
||||
stw r5, 208(r1)
|
||||
stw r6, 212(r1)
|
||||
stw r7, 216(r1)
|
||||
stw r8, 220(r1)
|
||||
stw r9, 224(r1)
|
||||
stw r10, 228(r1)
|
||||
|
||||
/* next save fpr 1 to fpr 13 (aligned to 8) */
|
||||
stfd f1, 56(r1)
|
||||
stfd f2, 64(r1)
|
||||
stfd f3, 72(r1)
|
||||
stfd f4, 80(r1)
|
||||
stfd f5, 88(r1)
|
||||
stfd f6, 96(r1)
|
||||
stfd f7, 104(r1)
|
||||
stfd f8, 112(r1)
|
||||
stfd f9, 120(r1)
|
||||
stfd f10, 128(r1)
|
||||
stfd f11, 136(r1)
|
||||
stfd f12, 144(r1)
|
||||
stfd f13, 152(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,160
|
||||
|
||||
/* now load up the pointer to the saved gpr registers */
|
||||
addi r5,r1,200
|
||||
|
||||
/* now load up the pointer to the saved fpr registers */
|
||||
addi r6,r1,56
|
||||
|
||||
/* make the call */
|
||||
bl .ffi_closure_helper_DARWIN
|
||||
nop
|
||||
|
||||
/* 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,160 /* get pointer to results area */
|
||||
lwz r4,LC..60(2) /* get address of jump table */
|
||||
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 */
|
||||
|
||||
L..60:
|
||||
.long L..44-L..60 /* FFI_TYPE_VOID */
|
||||
.long L..50-L..60 /* FFI_TYPE_INT */
|
||||
.long L..47-L..60 /* FFI_TYPE_FLOAT */
|
||||
.long L..46-L..60 /* FFI_TYPE_DOUBLE */
|
||||
.long L..46-L..60 /* FFI_TYPE_LONGDOUBLE */
|
||||
.long L..56-L..60 /* FFI_TYPE_UINT8 */
|
||||
.long L..55-L..60 /* FFI_TYPE_SINT8 */
|
||||
.long L..58-L..60 /* FFI_TYPE_UINT16 */
|
||||
.long L..57-L..60 /* FFI_TYPE_SINT16 */
|
||||
.long L..50-L..60 /* FFI_TYPE_UINT32 */
|
||||
.long L..50-L..60 /* FFI_TYPE_SINT32 */
|
||||
.long L..48-L..60 /* FFI_TYPE_UINT64 */
|
||||
.long L..48-L..60 /* FFI_TYPE_SINT64 */
|
||||
.long L..44-L..60 /* FFI_TYPE_STRUCT */
|
||||
.long L..50-L..60 /* FFI_TYPE_POINTER */
|
||||
|
||||
|
||||
/* case double */
|
||||
L..46:
|
||||
lfd f1,0(r5)
|
||||
b L..44
|
||||
|
||||
/* case float */
|
||||
L..47:
|
||||
lfs f1,0(r5)
|
||||
b L..44
|
||||
|
||||
/* case long long */
|
||||
L..48:
|
||||
lwz r3,0(r5)
|
||||
lwz r4,4(r5)
|
||||
b L..44
|
||||
|
||||
/* case default / int32 / pointer */
|
||||
L..50:
|
||||
lwz r3,0(r5)
|
||||
b L..44
|
||||
|
||||
/* case signed int8 */
|
||||
L..55:
|
||||
addi r5,r5,3
|
||||
lbz r3,0(r5)
|
||||
slwi r3,r3,24
|
||||
srawi r3,r3,24
|
||||
b L..44
|
||||
|
||||
/* case unsigned int8 */
|
||||
L..56:
|
||||
addi r5,r5,3
|
||||
lbz r3,0(r5)
|
||||
b L..44
|
||||
|
||||
/* case signed int16 */
|
||||
L..57:
|
||||
addi r5,r5,2
|
||||
lhz r3,0(r5)
|
||||
extsh r3,r3
|
||||
b L..44
|
||||
|
||||
/* case unsigned int16 */
|
||||
L..58:
|
||||
addi r5,r5,2
|
||||
lhz r3,0(r5)
|
||||
|
||||
/* case void / done */
|
||||
L..44:
|
||||
addi r1,r1,176 /* restore stack pointer */
|
||||
lwz r0,8(r1) /* get return address */
|
||||
mtlr r0 /* reset link register */
|
||||
blr
|
||||
|
||||
/* END(ffi_closure_ASM) */
|
||||
125
src/powerpc/.svn/text-base/asm.h.svn-base
Normal file
125
src/powerpc/.svn/text-base/asm.h.svn-base
Normal file
@@ -0,0 +1,125 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
asm.h - Copyright (c) 1998 Geoffrey Keating
|
||||
|
||||
PowerPC 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 ASM_GLOBAL_DIRECTIVE .globl
|
||||
|
||||
|
||||
#define C_SYMBOL_NAME(name) name
|
||||
/* Macro for a label. */
|
||||
#ifdef __STDC__
|
||||
#define C_LABEL(name) name##:
|
||||
#else
|
||||
#define C_LABEL(name) name/**/:
|
||||
#endif
|
||||
|
||||
/* This seems to always be the case on PPC. */
|
||||
#define ALIGNARG(log2) log2
|
||||
/* For ELF we need the `.type' directive to make shared libs work right. */
|
||||
#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg;
|
||||
#define ASM_SIZE_DIRECTIVE(name) .size name,.-name
|
||||
|
||||
/* If compiled for profiling, call `_mcount' at the start of each function. */
|
||||
#ifdef PROF
|
||||
/* The mcount code relies on a the return address being on the stack
|
||||
to locate our caller and so it can restore it; so store one just
|
||||
for its benefit. */
|
||||
#ifdef PIC
|
||||
#define CALL_MCOUNT \
|
||||
.pushsection; \
|
||||
.section ".data"; \
|
||||
.align ALIGNARG(2); \
|
||||
0:.long 0; \
|
||||
.previous; \
|
||||
mflr %r0; \
|
||||
stw %r0,4(%r1); \
|
||||
bl _GLOBAL_OFFSET_TABLE_@local-4; \
|
||||
mflr %r11; \
|
||||
lwz %r0,0b@got(%r11); \
|
||||
bl JUMPTARGET(_mcount);
|
||||
#else /* PIC */
|
||||
#define CALL_MCOUNT \
|
||||
.section ".data"; \
|
||||
.align ALIGNARG(2); \
|
||||
0:.long 0; \
|
||||
.previous; \
|
||||
mflr %r0; \
|
||||
lis %r11,0b@ha; \
|
||||
stw %r0,4(%r1); \
|
||||
addi %r0,%r11,0b@l; \
|
||||
bl JUMPTARGET(_mcount);
|
||||
#endif /* PIC */
|
||||
#else /* PROF */
|
||||
#define CALL_MCOUNT /* Do nothing. */
|
||||
#endif /* PROF */
|
||||
|
||||
#define ENTRY(name) \
|
||||
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \
|
||||
ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \
|
||||
.align ALIGNARG(2); \
|
||||
C_LABEL(name) \
|
||||
CALL_MCOUNT
|
||||
|
||||
#define EALIGN_W_0 /* No words to insert. */
|
||||
#define EALIGN_W_1 nop
|
||||
#define EALIGN_W_2 nop;nop
|
||||
#define EALIGN_W_3 nop;nop;nop
|
||||
#define EALIGN_W_4 EALIGN_W_3;nop
|
||||
#define EALIGN_W_5 EALIGN_W_4;nop
|
||||
#define EALIGN_W_6 EALIGN_W_5;nop
|
||||
#define EALIGN_W_7 EALIGN_W_6;nop
|
||||
|
||||
/* EALIGN is like ENTRY, but does alignment to 'words'*4 bytes
|
||||
past a 2^align boundary. */
|
||||
#ifdef PROF
|
||||
#define EALIGN(name, alignt, words) \
|
||||
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \
|
||||
ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \
|
||||
.align ALIGNARG(2); \
|
||||
C_LABEL(name) \
|
||||
CALL_MCOUNT \
|
||||
b 0f; \
|
||||
.align ALIGNARG(alignt); \
|
||||
EALIGN_W_##words; \
|
||||
0:
|
||||
#else /* PROF */
|
||||
#define EALIGN(name, alignt, words) \
|
||||
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \
|
||||
ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \
|
||||
.align ALIGNARG(alignt); \
|
||||
EALIGN_W_##words; \
|
||||
C_LABEL(name)
|
||||
#endif
|
||||
|
||||
#define END(name) \
|
||||
ASM_SIZE_DIRECTIVE(name)
|
||||
|
||||
#ifdef PIC
|
||||
#define JUMPTARGET(name) name##@plt
|
||||
#else
|
||||
#define JUMPTARGET(name) name
|
||||
#endif
|
||||
|
||||
/* Local labels stripped out by the linker. */
|
||||
#define L(x) .L##x
|
||||
245
src/powerpc/.svn/text-base/darwin.S.svn-base
Normal file
245
src/powerpc/.svn/text-base/darwin.S.svn-base
Normal file
@@ -0,0 +1,245 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
darwin.S - Copyright (c) 2000 John Hornkvist
|
||||
Copyright (c) 2004 Free Software Foundation, Inc.
|
||||
|
||||
PowerPC 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#if defined(__ppc64__)
|
||||
#define MODE_CHOICE(x, y) y
|
||||
#else
|
||||
#define MODE_CHOICE(x, y) x
|
||||
#endif
|
||||
|
||||
#define g_long MODE_CHOICE(long, quad) /* usage is ".g_long" */
|
||||
|
||||
#define LOG2_GPR_BYTES MODE_CHOICE(2,3) /* log2(GPR_BYTES) */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#define JUMPTARGET(name) name
|
||||
#define L(x) x
|
||||
.text
|
||||
.align 2
|
||||
.globl _ffi_prep_args
|
||||
|
||||
.text
|
||||
.align 2
|
||||
.globl _ffi_call_DARWIN
|
||||
.text
|
||||
.align 2
|
||||
_ffi_call_DARWIN:
|
||||
LFB0:
|
||||
mr r12,r8 /* We only need r12 until the call,
|
||||
so it doesn't have to be saved. */
|
||||
LFB1:
|
||||
/* Save the old stack pointer as AP. */
|
||||
mr r8,r1
|
||||
LCFI0:
|
||||
/* Allocate the stack space we need. */
|
||||
stwux r1,r1,r4
|
||||
|
||||
/* Save registers we use. */
|
||||
mflr r9
|
||||
|
||||
stw r28,-16(r8)
|
||||
stw r29,-12(r8)
|
||||
stw r30,-8(r8)
|
||||
stw r31,-4(r8)
|
||||
|
||||
stw r9,8(r8)
|
||||
stw r2,20(r1)
|
||||
LCFI1:
|
||||
|
||||
/* Save arguments over call. */
|
||||
mr r31,r5 /* flags, */
|
||||
mr r30,r6 /* rvalue, */
|
||||
mr r29,r7 /* function address, */
|
||||
mr r28,r8 /* our AP. */
|
||||
LCFI2:
|
||||
/* Call ffi_prep_args. */
|
||||
mr r4,r1
|
||||
li r9,0
|
||||
|
||||
mtctr r12 /* r12 holds address of _ffi_prep_args. */
|
||||
bctrl
|
||||
lwz r2,20(r1)
|
||||
|
||||
/* 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 r29
|
||||
/* Load all those argument registers.
|
||||
We have set up a nice stack frame, just load it into registers. */
|
||||
lwz r3,20+(1*4)(r1)
|
||||
lwz r4,20+(2*4)(r1)
|
||||
lwz r5,20+(3*4)(r1)
|
||||
lwz r6,20+(4*4)(r1)
|
||||
nop
|
||||
lwz r7,20+(5*4)(r1)
|
||||
lwz r8,20+(6*4)(r1)
|
||||
lwz r9,20+(7*4)(r1)
|
||||
lwz r10,20+(8*4)(r1)
|
||||
|
||||
L1:
|
||||
/* Load all the FP registers. */
|
||||
bf 6,L2 /* No floats to load. */
|
||||
lfd f1,-16-(13*8)(r28)
|
||||
lfd f2,-16-(12*8)(r28)
|
||||
lfd f3,-16-(11*8)(r28)
|
||||
lfd f4,-16-(10*8)(r28)
|
||||
nop
|
||||
lfd f5,-16-(9*8)(r28)
|
||||
lfd f6,-16-(8*8)(r28)
|
||||
lfd f7,-16-(7*8)(r28)
|
||||
lfd f8,-16-(6*8)(r28)
|
||||
nop
|
||||
lfd f9,-16-(5*8)(r28)
|
||||
lfd f10,-16-(4*8)(r28)
|
||||
lfd f11,-16-(3*8)(r28)
|
||||
lfd f12,-16-(2*8)(r28)
|
||||
nop
|
||||
lfd f13,-16-(1*8)(r28)
|
||||
|
||||
L2:
|
||||
mr r12,r29 /* Put the target address in r12 as specified. */
|
||||
mtctr r12
|
||||
nop
|
||||
nop
|
||||
/* Make the call. */
|
||||
bctrl
|
||||
|
||||
/* Now, deal with the return value. */
|
||||
mtcrf 0x01,r31
|
||||
|
||||
bt 30,L(done_return_value)
|
||||
bt 29,L(fp_return_value)
|
||||
stw r3,0(r30)
|
||||
bf 28,L(done_return_value)
|
||||
stw r4,4(r30)
|
||||
|
||||
/* Fall through. */
|
||||
|
||||
L(done_return_value):
|
||||
/* Restore the registers we used and return. */
|
||||
lwz r9,8(r28)
|
||||
lwz r31,-4(r28)
|
||||
mtlr r9
|
||||
lwz r30,-8(r28)
|
||||
lwz r29,-12(r28)
|
||||
lwz r28,-16(r28)
|
||||
lwz r1,0(r1)
|
||||
blr
|
||||
|
||||
L(fp_return_value):
|
||||
/* Do we have long double to store? */
|
||||
bf 31,L(fd_return_value)
|
||||
stfd f1,0(r30)
|
||||
stfd f2,8(r30)
|
||||
b L(done_return_value)
|
||||
|
||||
L(fd_return_value):
|
||||
/* Do we have double to store? */
|
||||
bf 28,L(float_return_value)
|
||||
stfd f1,0(r30)
|
||||
b L(done_return_value)
|
||||
|
||||
L(float_return_value):
|
||||
/* We only have a float to store. */
|
||||
stfs f1,0(r30)
|
||||
b L(done_return_value)
|
||||
|
||||
LFE1:
|
||||
/* END(_ffi_call_DARWIN) */
|
||||
|
||||
/* Provide a null definition of _ffi_call_AIX. */
|
||||
.text
|
||||
.align 2
|
||||
.globl _ffi_call_AIX
|
||||
.text
|
||||
.align 2
|
||||
_ffi_call_AIX:
|
||||
blr
|
||||
/* END(_ffi_call_AIX) */
|
||||
|
||||
.data
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0 ; Length of Common Information Entry
|
||||
LSCIE1:
|
||||
.long 0x0 ; CIE Identifier Tag
|
||||
.byte 0x1 ; CIE Version
|
||||
.ascii "zR\0" ; CIE Augmentation
|
||||
.byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
|
||||
.byte 0x41 ; CIE RA Column
|
||||
.byte 0x1 ; uleb128 0x1; Augmentation size
|
||||
.byte 0x90 ; FDE Encoding (indirect pcrel)
|
||||
.byte 0xc ; DW_CFA_def_cfa
|
||||
.byte 0x1 ; uleb128 0x1
|
||||
.byte 0x0 ; uleb128 0x0
|
||||
.align LOG2_GPR_BYTES
|
||||
LECIE1:
|
||||
.globl _ffi_call_DARWIN.eh
|
||||
_ffi_call_DARWIN.eh:
|
||||
LSFDE1:
|
||||
.set L$set$1,LEFDE1-LASFDE1
|
||||
.long L$set$1 ; FDE Length
|
||||
LASFDE1:
|
||||
.long LASFDE1-EH_frame1 ; FDE CIE offset
|
||||
.g_long LLFB0$non_lazy_ptr-. ; FDE initial location
|
||||
.set L$set$3,LFE1-LFB0
|
||||
.g_long L$set$3 ; FDE address range
|
||||
.byte 0x0 ; uleb128 0x0; Augmentation size
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$4,LCFI0-LFB1
|
||||
.long L$set$4
|
||||
.byte 0xd ; DW_CFA_def_cfa_register
|
||||
.byte 0x08 ; uleb128 0x08
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$5,LCFI1-LCFI0
|
||||
.long L$set$5
|
||||
.byte 0x11 ; DW_CFA_offset_extended_sf
|
||||
.byte 0x41 ; uleb128 0x41
|
||||
.byte 0x7e ; sleb128 -2
|
||||
.byte 0x9f ; DW_CFA_offset, column 0x1f
|
||||
.byte 0x1 ; uleb128 0x1
|
||||
.byte 0x9e ; DW_CFA_offset, column 0x1e
|
||||
.byte 0x2 ; uleb128 0x2
|
||||
.byte 0x9d ; DW_CFA_offset, column 0x1d
|
||||
.byte 0x3 ; uleb128 0x3
|
||||
.byte 0x9c ; DW_CFA_offset, column 0x1c
|
||||
.byte 0x4 ; uleb128 0x4
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$6,LCFI2-LCFI1
|
||||
.long L$set$6
|
||||
.byte 0xd ; DW_CFA_def_cfa_register
|
||||
.byte 0x1c ; uleb128 0x1c
|
||||
.align LOG2_GPR_BYTES
|
||||
LEFDE1:
|
||||
.data
|
||||
.align LOG2_GPR_BYTES
|
||||
LLFB0$non_lazy_ptr:
|
||||
.g_long LFB0
|
||||
317
src/powerpc/.svn/text-base/darwin_closure.S.svn-base
Normal file
317
src/powerpc/.svn/text-base/darwin_closure.S.svn-base
Normal file
@@ -0,0 +1,317 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
|
||||
Inc. based on ppc_closure.S
|
||||
|
||||
PowerPC 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
|
||||
#define L(x) x
|
||||
|
||||
#if defined(__ppc64__)
|
||||
#define MODE_CHOICE(x, y) y
|
||||
#else
|
||||
#define MODE_CHOICE(x, y) x
|
||||
#endif
|
||||
|
||||
#define lgu MODE_CHOICE(lwzu, ldu)
|
||||
|
||||
#define g_long MODE_CHOICE(long, quad) /* usage is ".g_long" */
|
||||
|
||||
#define LOG2_GPR_BYTES MODE_CHOICE(2,3) /* log2(GPR_BYTES) */
|
||||
|
||||
.file "darwin_closure.S"
|
||||
.text
|
||||
.align LOG2_GPR_BYTES
|
||||
.globl _ffi_closure_ASM
|
||||
|
||||
.text
|
||||
.align LOG2_GPR_BYTES
|
||||
_ffi_closure_ASM:
|
||||
LFB1:
|
||||
mflr r0 /* extract return address */
|
||||
stw r0,8(r1) /* save the return address */
|
||||
LCFI0:
|
||||
/* 24 Bytes (Linkage Area)
|
||||
32 Bytes (outgoing parameter area, always reserved)
|
||||
104 Bytes (13*8 from FPR)
|
||||
16 Bytes (result)
|
||||
176 Bytes */
|
||||
|
||||
stwu r1,-176(r1) /* skip over caller save area
|
||||
keep stack aligned to 16. */
|
||||
LCFI1:
|
||||
/* We want to build up an area for the parameters passed
|
||||
in registers. (both floating point and integer) */
|
||||
|
||||
/* We store gpr 3 to gpr 10 (aligned to 4)
|
||||
in the parents outgoing area. */
|
||||
stw r3,200(r1)
|
||||
stw r4,204(r1)
|
||||
stw r5,208(r1)
|
||||
stw r6,212(r1)
|
||||
stw r7,216(r1)
|
||||
stw r8,220(r1)
|
||||
stw r9,224(r1)
|
||||
stw r10,228(r1)
|
||||
|
||||
/* We save fpr 1 to fpr 13. (aligned to 8) */
|
||||
stfd f1,56(r1)
|
||||
stfd f2,64(r1)
|
||||
stfd f3,72(r1)
|
||||
stfd f4,80(r1)
|
||||
stfd f5,88(r1)
|
||||
stfd f6,96(r1)
|
||||
stfd f7,104(r1)
|
||||
stfd f8,112(r1)
|
||||
stfd f9,120(r1)
|
||||
stfd f10,128(r1)
|
||||
stfd f11,136(r1)
|
||||
stfd f12,144(r1)
|
||||
stfd f13,152(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,160
|
||||
|
||||
/* Now load up the pointer to the saved gpr registers. */
|
||||
addi r5,r1,200
|
||||
|
||||
/* Now load up the pointer to the saved fpr registers. */
|
||||
addi r6,r1,56
|
||||
|
||||
/* Make the call. */
|
||||
bl Lffi_closure_helper_DARWIN$stub
|
||||
|
||||
/* 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,160 /* Get pointer to results area. */
|
||||
bl Lget_ret_type0_addr /* Get pointer to Lret_type0 into LR. */
|
||||
mflr r4 /* Move to r4. */
|
||||
slwi 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. */
|
||||
LFE1:
|
||||
/* 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
|
||||
|
||||
/* case FFI_TYPE_VOID */
|
||||
Lret_type0:
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_INT */
|
||||
Lret_type1:
|
||||
lwz r3,0(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_FLOAT */
|
||||
Lret_type2:
|
||||
lfs f1,0(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_DOUBLE */
|
||||
Lret_type3:
|
||||
lfd f1,0(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_LONGDOUBLE */
|
||||
Lret_type4:
|
||||
lfd f1,0(r5)
|
||||
lfd f2,8(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_UINT8 */
|
||||
Lret_type5:
|
||||
lbz r3,3(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_SINT8 */
|
||||
Lret_type6:
|
||||
lbz r3,3(r5)
|
||||
extsb r3,r3
|
||||
b Lfinish
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_UINT16 */
|
||||
Lret_type7:
|
||||
lhz r3,2(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_SINT16 */
|
||||
Lret_type8:
|
||||
lha r3,2(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_UINT32 */
|
||||
Lret_type9:
|
||||
lwz r3,0(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_SINT32 */
|
||||
Lret_type10:
|
||||
lwz r3,0(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_UINT64 */
|
||||
Lret_type11:
|
||||
lwz r3,0(r5)
|
||||
lwz r4,4(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_SINT64 */
|
||||
Lret_type12:
|
||||
lwz r3,0(r5)
|
||||
lwz r4,4(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_STRUCT */
|
||||
Lret_type13:
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_POINTER */
|
||||
Lret_type14:
|
||||
lwz r3,0(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case done */
|
||||
Lfinish:
|
||||
addi r1,r1,176 /* Restore stack pointer. */
|
||||
lwz r0,8(r1) /* Get return address. */
|
||||
mtlr r0 /* Reset link register. */
|
||||
blr
|
||||
|
||||
/* END(ffi_closure_ASM) */
|
||||
|
||||
.data
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0 ; Length of Common Information Entry
|
||||
LSCIE1:
|
||||
.long 0x0 ; CIE Identifier Tag
|
||||
.byte 0x1 ; CIE Version
|
||||
.ascii "zR\0" ; CIE Augmentation
|
||||
.byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
|
||||
.byte 0x41 ; CIE RA Column
|
||||
.byte 0x1 ; uleb128 0x1; Augmentation size
|
||||
.byte 0x90 ; FDE Encoding (indirect pcrel)
|
||||
.byte 0xc ; DW_CFA_def_cfa
|
||||
.byte 0x1 ; uleb128 0x1
|
||||
.byte 0x0 ; uleb128 0x0
|
||||
.align LOG2_GPR_BYTES
|
||||
LECIE1:
|
||||
.globl _ffi_closure_ASM.eh
|
||||
_ffi_closure_ASM.eh:
|
||||
LSFDE1:
|
||||
.set L$set$1,LEFDE1-LASFDE1
|
||||
.long L$set$1 ; FDE Length
|
||||
|
||||
LASFDE1:
|
||||
.long LASFDE1-EH_frame1 ; FDE CIE offset
|
||||
.g_long LLFB1$non_lazy_ptr-. ; FDE initial location
|
||||
.set L$set$3,LFE1-LFB1
|
||||
.g_long L$set$3 ; FDE address range
|
||||
.byte 0x0 ; uleb128 0x0; Augmentation size
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$3,LCFI1-LCFI0
|
||||
.long L$set$3
|
||||
.byte 0xe ; DW_CFA_def_cfa_offset
|
||||
.byte 176,1 ; uleb128 176
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$4,LCFI0-LFB1
|
||||
.long L$set$4
|
||||
.byte 0x11 ; DW_CFA_offset_extended_sf
|
||||
.byte 0x41 ; uleb128 0x41
|
||||
.byte 0x7e ; sleb128 -2
|
||||
.align LOG2_GPR_BYTES
|
||||
LEFDE1:
|
||||
.data
|
||||
.align LOG2_GPR_BYTES
|
||||
LDFCM0:
|
||||
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
||||
.align LOG2_GPR_BYTES
|
||||
Lffi_closure_helper_DARWIN$stub:
|
||||
#if 1
|
||||
.indirect_symbol _ffi_closure_helper_DARWIN
|
||||
mflr r0
|
||||
bcl 20,31,LO$ffi_closure_helper_DARWIN
|
||||
LO$ffi_closure_helper_DARWIN:
|
||||
mflr r11
|
||||
addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)
|
||||
mtlr r0
|
||||
lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11)
|
||||
mtctr r12
|
||||
bctr
|
||||
.lazy_symbol_pointer
|
||||
L_ffi_closure_helper_DARWIN$lazy_ptr:
|
||||
.indirect_symbol _ffi_closure_helper_DARWIN
|
||||
.g_long dyld_stub_binding_helper
|
||||
#endif
|
||||
.data
|
||||
.align LOG2_GPR_BYTES
|
||||
LLFB1$non_lazy_ptr:
|
||||
.g_long LFB1
|
||||
1439
src/powerpc/.svn/text-base/ffi.c.svn-base
Normal file
1439
src/powerpc/.svn/text-base/ffi.c.svn-base
Normal file
File diff suppressed because it is too large
Load Diff
800
src/powerpc/.svn/text-base/ffi_darwin.c.svn-base
Normal file
800
src/powerpc/.svn/text-base/ffi_darwin.c.svn-base
Normal file
@@ -0,0 +1,800 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi_darwin.c
|
||||
|
||||
Copyright (C) 1998 Geoffrey Keating
|
||||
Copyright (C) 2001 John Hornkvist
|
||||
Copyright (C) 2002, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
FFI support for Darwin and AIX.
|
||||
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
extern void ffi_closure_ASM(void);
|
||||
|
||||
enum {
|
||||
/* The assembly depends on these exact flags. */
|
||||
FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */
|
||||
FLAG_RETURNS_FP = 1 << (31-29),
|
||||
FLAG_RETURNS_64BITS = 1 << (31-28),
|
||||
FLAG_RETURNS_128BITS = 1 << (31-31),
|
||||
|
||||
FLAG_ARG_NEEDS_COPY = 1 << (31- 7),
|
||||
FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */
|
||||
FLAG_4_GPR_ARGUMENTS = 1 << (31- 5),
|
||||
FLAG_RETVAL_REFERENCE = 1 << (31- 4)
|
||||
};
|
||||
|
||||
/* About the DARWIN ABI. */
|
||||
enum {
|
||||
NUM_GPR_ARG_REGISTERS = 8,
|
||||
NUM_FPR_ARG_REGISTERS = 13
|
||||
};
|
||||
enum { ASM_NEEDS_REGISTERS = 4 };
|
||||
|
||||
/* 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:
|
||||
|
||||
| Return address from ffi_call_DARWIN | higher addresses
|
||||
|--------------------------------------------|
|
||||
| Previous backchain pointer 4 | stack pointer here
|
||||
|--------------------------------------------|<+ <<< on entry to
|
||||
| Saved r28-r31 4*4 | | ffi_call_DARWIN
|
||||
|--------------------------------------------| |
|
||||
| Parameters (at least 8*4=32) | |
|
||||
|--------------------------------------------| |
|
||||
| Space for GPR2 4 | |
|
||||
|--------------------------------------------| | stack |
|
||||
| Reserved 2*4 | | grows |
|
||||
|--------------------------------------------| | down V
|
||||
| Space for callee's LR 4 | |
|
||||
|--------------------------------------------| | lower addresses
|
||||
| Saved CR 4 | |
|
||||
|--------------------------------------------| | stack pointer here
|
||||
| Current backchain pointer 4 |-/ during
|
||||
|--------------------------------------------| <<< ffi_call_DARWIN
|
||||
|
||||
*/
|
||||
|
||||
void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
|
||||
{
|
||||
const unsigned bytes = ecif->cif->bytes;
|
||||
const unsigned flags = ecif->cif->flags;
|
||||
|
||||
/* 'stacktop' points at the previous backchain pointer. */
|
||||
unsigned *const stacktop = stack + (bytes / sizeof(unsigned));
|
||||
|
||||
/* 'fpr_base' points at the space for fpr1, and grows upwards as
|
||||
we use FPR registers. */
|
||||
double *fpr_base = (double*) (stacktop - ASM_NEEDS_REGISTERS) - NUM_FPR_ARG_REGISTERS;
|
||||
int fparg_count = 0;
|
||||
|
||||
|
||||
/* 'next_arg' grows up as we put parameters in it. */
|
||||
unsigned *next_arg = stack + 6; /* 6 reserved positions. */
|
||||
|
||||
int i = ecif->cif->nargs;
|
||||
double double_tmp;
|
||||
void **p_argv = ecif->avalue;
|
||||
unsigned gprvalue;
|
||||
ffi_type** ptr = ecif->cif->arg_types;
|
||||
char *dest_cpy;
|
||||
unsigned size_al = 0;
|
||||
|
||||
/* Check that everything starts aligned properly. */
|
||||
FFI_ASSERT(((unsigned)(char *)stack & 0xF) == 0);
|
||||
FFI_ASSERT(((unsigned)(char *)stacktop & 0xF) == 0);
|
||||
FFI_ASSERT((bytes & 0xF) == 0);
|
||||
|
||||
/* Deal with return values that are actually pass-by-reference.
|
||||
Rule:
|
||||
Return values are referenced by r3, so r4 is the first parameter. */
|
||||
|
||||
if (flags & FLAG_RETVAL_REFERENCE)
|
||||
*next_arg++ = (unsigned)(char *)ecif->rvalue;
|
||||
|
||||
/* Now for the arguments. */
|
||||
for (;
|
||||
i > 0;
|
||||
i--, ptr++, p_argv++)
|
||||
{
|
||||
switch ((*ptr)->type)
|
||||
{
|
||||
/* If a floating-point parameter appears before all of the general-
|
||||
purpose registers are filled, the corresponding GPRs that match
|
||||
the size of the floating-point parameter are skipped. */
|
||||
case FFI_TYPE_FLOAT:
|
||||
double_tmp = *(float *)*p_argv;
|
||||
if (fparg_count >= NUM_FPR_ARG_REGISTERS)
|
||||
*(double *)next_arg = double_tmp;
|
||||
else
|
||||
*fpr_base++ = double_tmp;
|
||||
next_arg++;
|
||||
fparg_count++;
|
||||
FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
double_tmp = *(double *)*p_argv;
|
||||
if (fparg_count >= NUM_FPR_ARG_REGISTERS)
|
||||
*(double *)next_arg = double_tmp;
|
||||
else
|
||||
*fpr_base++ = double_tmp;
|
||||
next_arg += 2;
|
||||
fparg_count++;
|
||||
FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
|
||||
break;
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
double_tmp = ((double *)*p_argv)[0];
|
||||
if (fparg_count >= NUM_FPR_ARG_REGISTERS)
|
||||
*(double *)next_arg = double_tmp;
|
||||
else
|
||||
*fpr_base++ = double_tmp;
|
||||
next_arg += 2;
|
||||
fparg_count++;
|
||||
double_tmp = ((double *)*p_argv)[1];
|
||||
if (fparg_count >= NUM_FPR_ARG_REGISTERS)
|
||||
*(double *)next_arg = double_tmp;
|
||||
else
|
||||
*fpr_base++ = double_tmp;
|
||||
next_arg += 2;
|
||||
fparg_count++;
|
||||
FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
|
||||
break;
|
||||
#endif
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
*(long long *)next_arg = *(long long *)*p_argv;
|
||||
next_arg+=2;
|
||||
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_STRUCT:
|
||||
dest_cpy = (char *) next_arg;
|
||||
|
||||
/* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
|
||||
SI 4 bytes) are aligned as if they were those modes.
|
||||
Structures with 3 byte in size are padded upwards. */
|
||||
size_al = (*ptr)->size;
|
||||
/* If the first member of the struct is a double, then align
|
||||
the struct to double-word.
|
||||
Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */
|
||||
if ((*ptr)->elements[0]->type == 3)
|
||||
size_al = ALIGN((*ptr)->size, 8);
|
||||
if (size_al < 3 && ecif->cif->abi == FFI_DARWIN)
|
||||
dest_cpy += 4 - size_al;
|
||||
|
||||
memcpy((char *)dest_cpy, (char *)*p_argv, size_al);
|
||||
next_arg += (size_al + 3) / 4;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_POINTER:
|
||||
gprvalue = *(unsigned *)*p_argv;
|
||||
putgpr:
|
||||
*next_arg++ = gprvalue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that we didn't overrun the stack... */
|
||||
//FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
|
||||
//FFI_ASSERT((unsigned *)fpr_base
|
||||
// <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
|
||||
//FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
|
||||
}
|
||||
|
||||
/* Adjust the size of S to be correct for Darwin.
|
||||
On Darwin, the first field of a structure has natural alignment. */
|
||||
|
||||
static void
|
||||
darwin_adjust_aggregate_sizes (ffi_type *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (s->type != FFI_TYPE_STRUCT)
|
||||
return;
|
||||
|
||||
s->size = 0;
|
||||
for (i = 0; s->elements[i] != NULL; i++)
|
||||
{
|
||||
ffi_type *p;
|
||||
int align;
|
||||
|
||||
p = s->elements[i];
|
||||
darwin_adjust_aggregate_sizes (p);
|
||||
if (i == 0
|
||||
&& (p->type == FFI_TYPE_UINT64
|
||||
|| p->type == FFI_TYPE_SINT64
|
||||
|| p->type == FFI_TYPE_DOUBLE
|
||||
|| p->alignment == 8))
|
||||
align = 8;
|
||||
else if (p->alignment == 16 || p->alignment < 4)
|
||||
align = p->alignment;
|
||||
else
|
||||
align = 4;
|
||||
s->size = ALIGN(s->size, align) + p->size;
|
||||
}
|
||||
|
||||
s->size = ALIGN(s->size, s->alignment);
|
||||
|
||||
if (s->elements[0]->type == FFI_TYPE_UINT64
|
||||
|| s->elements[0]->type == FFI_TYPE_SINT64
|
||||
|| s->elements[0]->type == FFI_TYPE_DOUBLE
|
||||
|| s->elements[0]->alignment == 8)
|
||||
s->alignment = s->alignment > 8 ? s->alignment : 8;
|
||||
/* Do not add additional tail padding. */
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing. */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
/* All this is for the DARWIN ABI. */
|
||||
int i;
|
||||
ffi_type **ptr;
|
||||
unsigned bytes;
|
||||
int fparg_count = 0, intarg_count = 0;
|
||||
unsigned flags = 0;
|
||||
unsigned size_al = 0;
|
||||
|
||||
/* All the machine-independent calculation of cif->bytes will be wrong.
|
||||
All the calculation of structure sizes will also be wrong.
|
||||
Redo the calculation for DARWIN. */
|
||||
|
||||
if (cif->abi == FFI_DARWIN)
|
||||
{
|
||||
darwin_adjust_aggregate_sizes (cif->rtype);
|
||||
for (i = 0; i < cif->nargs; i++)
|
||||
darwin_adjust_aggregate_sizes (cif->arg_types[i]);
|
||||
}
|
||||
|
||||
/* Space for the frame pointer, callee's LR, CR, etc, and for
|
||||
the asm's temp regs. */
|
||||
|
||||
bytes = (6 + ASM_NEEDS_REGISTERS) * sizeof(long);
|
||||
|
||||
/* Return value handling. The rules 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;
|
||||
- Long double FP (if not equivalent to double) values are returned in
|
||||
fpr1 and fpr2;
|
||||
- Larger structures values are allocated space and a pointer is passed
|
||||
as the first argument. */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
flags |= FLAG_RETURNS_128BITS;
|
||||
flags |= FLAG_RETURNS_FP;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
flags |= FLAG_RETURNS_64BITS;
|
||||
/* Fall through. */
|
||||
case FFI_TYPE_FLOAT:
|
||||
flags |= FLAG_RETURNS_FP;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
flags |= FLAG_RETURNS_64BITS;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
flags |= FLAG_RETVAL_REFERENCE;
|
||||
flags |= FLAG_RETURNS_NOTHING;
|
||||
intarg_count++;
|
||||
break;
|
||||
case FFI_TYPE_VOID:
|
||||
flags |= FLAG_RETURNS_NOTHING;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Returns 32-bit integer, or similar. Nothing to do here. */
|
||||
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 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:
|
||||
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;
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
fparg_count += 2;
|
||||
/* 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++;
|
||||
intarg_count +=2;
|
||||
break;
|
||||
#endif
|
||||
|
||||
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:
|
||||
size_al = (*ptr)->size;
|
||||
/* If the first member of the struct is a double, then align
|
||||
the struct to double-word.
|
||||
Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */
|
||||
if ((*ptr)->elements[0]->type == 3)
|
||||
size_al = ALIGN((*ptr)->size, 8);
|
||||
intarg_count += (size_al + 3) / 4;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (fparg_count != 0)
|
||||
flags |= FLAG_FP_ARGUMENTS;
|
||||
|
||||
/* Space for the FPR registers, if needed. */
|
||||
if (fparg_count != 0)
|
||||
bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
|
||||
|
||||
/* Stack space. */
|
||||
if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS)
|
||||
bytes += (intarg_count + 2 * fparg_count) * sizeof(long);
|
||||
else
|
||||
bytes += NUM_GPR_ARG_REGISTERS * sizeof(long);
|
||||
|
||||
/* The stack space allocated needs to be a multiple of 16 bytes. */
|
||||
bytes = (bytes + 15) & ~0xF;
|
||||
|
||||
cif->flags = flags;
|
||||
cif->bytes = bytes;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern void ffi_call_AIX(extended_cif *, unsigned, unsigned, unsigned *,
|
||||
void (*fn)(void), void (*fn2)(void));
|
||||
extern void ffi_call_DARWIN(extended_cif *, unsigned, unsigned, unsigned *,
|
||||
void (*fn)(void), void (*fn2)(void));
|
||||
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(void), 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_AIX:
|
||||
ffi_call_AIX(&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn,
|
||||
ffi_prep_args);
|
||||
break;
|
||||
case FFI_DARWIN:
|
||||
ffi_call_DARWIN(&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn,
|
||||
ffi_prep_args);
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void flush_icache(char *);
|
||||
static void flush_range(char *, int);
|
||||
|
||||
/* The layout of a function descriptor. A C function pointer really
|
||||
points to one of these. */
|
||||
|
||||
typedef struct aix_fd_struct {
|
||||
void *code_pointer;
|
||||
void *toc;
|
||||
} aix_fd;
|
||||
|
||||
/* here I'd like to add the stack frame layout we use in darwin_closure.S
|
||||
and aix_clsoure.S
|
||||
|
||||
SP previous -> +---------------------------------------+ <--- child frame
|
||||
| back chain to caller 4 |
|
||||
+---------------------------------------+ 4
|
||||
| saved CR 4 |
|
||||
+---------------------------------------+ 8
|
||||
| saved LR 4 |
|
||||
+---------------------------------------+ 12
|
||||
| reserved for compilers 4 |
|
||||
+---------------------------------------+ 16
|
||||
| reserved for binders 4 |
|
||||
+---------------------------------------+ 20
|
||||
| saved TOC pointer 4 |
|
||||
+---------------------------------------+ 24
|
||||
| always reserved 8*4=32 (previous GPRs)|
|
||||
| according to the linkage convention |
|
||||
| from AIX |
|
||||
+---------------------------------------+ 56
|
||||
| our FPR area 13*8=104 |
|
||||
| f1 |
|
||||
| . |
|
||||
| f13 |
|
||||
+---------------------------------------+ 160
|
||||
| result area 8 |
|
||||
+---------------------------------------+ 168
|
||||
| alignement to the next multiple of 16 |
|
||||
SP current --> +---------------------------------------+ 176 <- parent frame
|
||||
| back chain to caller 4 |
|
||||
+---------------------------------------+ 180
|
||||
| saved CR 4 |
|
||||
+---------------------------------------+ 184
|
||||
| saved LR 4 |
|
||||
+---------------------------------------+ 188
|
||||
| reserved for compilers 4 |
|
||||
+---------------------------------------+ 192
|
||||
| reserved for binders 4 |
|
||||
+---------------------------------------+ 196
|
||||
| saved TOC pointer 4 |
|
||||
+---------------------------------------+ 200
|
||||
| always reserved 8*4=32 we store our |
|
||||
| GPRs here |
|
||||
| r3 |
|
||||
| . |
|
||||
| r10 |
|
||||
+---------------------------------------+ 232
|
||||
| overflow part |
|
||||
+---------------------------------------+ xxx
|
||||
| ???? |
|
||||
+---------------------------------------+ xxx
|
||||
|
||||
*/
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
unsigned int *tramp;
|
||||
struct ffi_aix_trampoline_struct *tramp_aix;
|
||||
aix_fd *fd;
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_DARWIN:
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_DARWIN);
|
||||
|
||||
tramp = (unsigned int *) &closure->tramp[0];
|
||||
tramp[0] = 0x7c0802a6; /* mflr r0 */
|
||||
tramp[1] = 0x429f000d; /* bcl- 20,4*cr7+so,0x10 */
|
||||
tramp[4] = 0x7d6802a6; /* mflr r11 */
|
||||
tramp[5] = 0x818b0000; /* lwz r12,0(r11) function address */
|
||||
tramp[6] = 0x7c0803a6; /* mtlr r0 */
|
||||
tramp[7] = 0x7d8903a6; /* mtctr r12 */
|
||||
tramp[8] = 0x816b0004; /* lwz r11,4(r11) static chain */
|
||||
tramp[9] = 0x4e800420; /* bctr */
|
||||
tramp[2] = (unsigned long) ffi_closure_ASM; /* function */
|
||||
tramp[3] = (unsigned long) codeloc; /* context */
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
/* Flush the icache. Only necessary on Darwin. */
|
||||
flush_range(codeloc, FFI_TRAMPOLINE_SIZE);
|
||||
|
||||
break;
|
||||
|
||||
case FFI_AIX:
|
||||
|
||||
tramp_aix = (struct ffi_aix_trampoline_struct *) (closure->tramp);
|
||||
fd = (aix_fd *)(void *)ffi_closure_ASM;
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_AIX);
|
||||
|
||||
tramp_aix->code_pointer = fd->code_pointer;
|
||||
tramp_aix->toc = fd->toc;
|
||||
tramp_aix->static_chain = codeloc;
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
default:
|
||||
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
flush_icache(char *addr)
|
||||
{
|
||||
#ifndef _AIX
|
||||
__asm__ volatile (
|
||||
"dcbf 0,%0\n"
|
||||
"\tsync\n"
|
||||
"\ticbi 0,%0\n"
|
||||
"\tsync\n"
|
||||
"\tisync"
|
||||
: : "r"(addr) : "memory");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
flush_range(char * addr1, int size)
|
||||
{
|
||||
#define MIN_LINE_SIZE 32
|
||||
int i;
|
||||
for (i = 0; i < size; i += MIN_LINE_SIZE)
|
||||
flush_icache(addr1+i);
|
||||
flush_icache(addr1+size-1);
|
||||
}
|
||||
|
||||
typedef union
|
||||
{
|
||||
float f;
|
||||
double d;
|
||||
} ffi_dblfl;
|
||||
|
||||
int ffi_closure_helper_DARWIN (ffi_closure*, void*,
|
||||
unsigned long*, ffi_dblfl*);
|
||||
|
||||
/* Basically the trampoline invokes ffi_closure_ASM, 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_ASM invokes the
|
||||
following helper function to do most of the work. */
|
||||
|
||||
int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
|
||||
unsigned long * pgr, ffi_dblfl * pfr)
|
||||
{
|
||||
/* 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_ASM
|
||||
pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM. */
|
||||
|
||||
typedef double ldbits[2];
|
||||
|
||||
union ldu
|
||||
{
|
||||
ldbits lb;
|
||||
long double ld;
|
||||
};
|
||||
|
||||
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;
|
||||
unsigned size_al;
|
||||
union ldu temp_ld;
|
||||
|
||||
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 *) *pgr;
|
||||
pgr++;
|
||||
ng++;
|
||||
}
|
||||
|
||||
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 *) pgr + 3;
|
||||
ng++;
|
||||
pgr++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
avalue[i] = (char *) pgr + 2;
|
||||
ng++;
|
||||
pgr++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_POINTER:
|
||||
avalue[i] = pgr;
|
||||
ng++;
|
||||
pgr++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
|
||||
SI 4 bytes) are aligned as if they were those modes. */
|
||||
size_al = arg_types[i]->size;
|
||||
/* If the first member of the struct is a double, then align
|
||||
the struct to double-word.
|
||||
Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */
|
||||
if (arg_types[i]->elements[0]->type == 3)
|
||||
size_al = ALIGN(arg_types[i]->size, 8);
|
||||
if (size_al < 3 && cif->abi == FFI_DARWIN)
|
||||
avalue[i] = (void*) pgr + 4 - size_al;
|
||||
else
|
||||
avalue[i] = (void*) pgr;
|
||||
ng += (size_al + 3) / 4;
|
||||
pgr += (size_al + 3) / 4;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
/* Long long ints are passed in two gpr's. */
|
||||
avalue[i] = pgr;
|
||||
ng += 2;
|
||||
pgr += 2;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
/* A float value consumes a GPR.
|
||||
There are 13 64bit floating point registers. */
|
||||
if (nf < NUM_FPR_ARG_REGISTERS)
|
||||
{
|
||||
temp = pfr->d;
|
||||
pfr->f = (float)temp;
|
||||
avalue[i] = pfr;
|
||||
pfr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
avalue[i] = pgr;
|
||||
}
|
||||
nf++;
|
||||
ng++;
|
||||
pgr++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
/* A double value consumes two GPRs.
|
||||
There are 13 64bit floating point registers. */
|
||||
if (nf < NUM_FPR_ARG_REGISTERS)
|
||||
{
|
||||
avalue[i] = pfr;
|
||||
pfr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
avalue[i] = pgr;
|
||||
}
|
||||
nf++;
|
||||
ng += 2;
|
||||
pgr += 2;
|
||||
break;
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* A long double value consumes four GPRs and two FPRs.
|
||||
There are 13 64bit floating point registers. */
|
||||
if (nf < NUM_FPR_ARG_REGISTERS - 1)
|
||||
{
|
||||
avalue[i] = pfr;
|
||||
pfr += 2;
|
||||
}
|
||||
/* Here we have the situation where one part of the long double
|
||||
is stored in fpr13 and the other part is already on the stack.
|
||||
We use a union to pass the long double to avalue[i]. */
|
||||
else if (nf == NUM_FPR_ARG_REGISTERS - 1)
|
||||
{
|
||||
memcpy (&temp_ld.lb[0], pfr, sizeof(ldbits));
|
||||
memcpy (&temp_ld.lb[1], pgr + 2, sizeof(ldbits));
|
||||
avalue[i] = &temp_ld.ld;
|
||||
}
|
||||
else
|
||||
{
|
||||
avalue[i] = pgr;
|
||||
}
|
||||
nf += 2;
|
||||
ng += 4;
|
||||
pgr += 4;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
/* Tell ffi_closure_ASM to perform return type promotions. */
|
||||
return cif->rtype->type;
|
||||
}
|
||||
122
src/powerpc/.svn/text-base/ffitarget.h.svn-base
Normal file
122
src/powerpc/.svn/text-base/ffitarget.h.svn-base
Normal file
@@ -0,0 +1,122 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Copyright (C) 2007, 2008 Free Software Foundation, Inc
|
||||
Target configuration macros for PowerPC.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
/* ---- System specific configurations ----------------------------------- */
|
||||
|
||||
#if defined (POWERPC) && defined (__powerpc64__)
|
||||
#define POWERPC64
|
||||
#endif
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
|
||||
#ifdef POWERPC
|
||||
FFI_SYSV,
|
||||
FFI_GCC_SYSV,
|
||||
FFI_LINUX64,
|
||||
FFI_LINUX,
|
||||
FFI_LINUX_SOFT_FLOAT,
|
||||
# ifdef POWERPC64
|
||||
FFI_DEFAULT_ABI = FFI_LINUX64,
|
||||
# else
|
||||
# if (!defined(__NO_FPRS__) && (__LDBL_MANT_DIG__ == 106))
|
||||
FFI_DEFAULT_ABI = FFI_LINUX,
|
||||
# else
|
||||
# ifdef __NO_FPRS__
|
||||
FFI_DEFAULT_ABI = FFI_LINUX_SOFT_FLOAT,
|
||||
# else
|
||||
FFI_DEFAULT_ABI = FFI_GCC_SYSV,
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef POWERPC_AIX
|
||||
FFI_AIX,
|
||||
FFI_DARWIN,
|
||||
FFI_DEFAULT_ABI = FFI_AIX,
|
||||
#endif
|
||||
|
||||
#ifdef POWERPC_DARWIN
|
||||
FFI_AIX,
|
||||
FFI_DARWIN,
|
||||
FFI_DEFAULT_ABI = FFI_DARWIN,
|
||||
#endif
|
||||
|
||||
#ifdef POWERPC_FREEBSD
|
||||
FFI_SYSV,
|
||||
FFI_GCC_SYSV,
|
||||
FFI_LINUX64,
|
||||
FFI_LINUX,
|
||||
FFI_LINUX_SOFT_FLOAT,
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
#endif
|
||||
|
||||
FFI_LAST_ABI
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
/* For additional types like the below, take care about the order in
|
||||
ppc_closures.S. They must follow after the FFI_TYPE_LAST. */
|
||||
|
||||
/* Needed for soft-float long-double-128 support. */
|
||||
#define FFI_TYPE_UINT128 (FFI_TYPE_LAST + 1)
|
||||
|
||||
/* Needed for FFI_SYSV small structure returns.
|
||||
We use two flag bits, (FLAG_SYSV_SMST_R3, FLAG_SYSV_SMST_R4) which are
|
||||
defined in ffi.c, to determine the exact return type and its size. */
|
||||
#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 2)
|
||||
|
||||
#if defined(POWERPC64) || defined(POWERPC_AIX)
|
||||
#define FFI_TRAMPOLINE_SIZE 24
|
||||
#else /* POWERPC || POWERPC_AIX */
|
||||
#define FFI_TRAMPOLINE_SIZE 40
|
||||
#endif
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
#if defined(POWERPC_DARWIN) || defined(POWERPC_AIX)
|
||||
struct ffi_aix_trampoline_struct {
|
||||
void * code_pointer; /* Pointer to ffi_closure_ASM */
|
||||
void * toc; /* TOC */
|
||||
void * static_chain; /* Pointer to closure */
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
187
src/powerpc/.svn/text-base/linux64.S.svn-base
Normal file
187
src/powerpc/.svn/text-base/linux64.S.svn-base
Normal file
@@ -0,0 +1,187 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@redhat.com>
|
||||
Copyright (c) 2008 Red Hat, Inc.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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 <fficonfig.h>
|
||||
#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. */
|
||||
.LCFI0:
|
||||
stdux %r1, %r1, %r4
|
||||
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*8)(%r28)
|
||||
ld %r8, -32-(3*8)(%r28)
|
||||
ld %r9, -32-(2*8)(%r28)
|
||||
ld %r10, -32-(1*8)(%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:
|
||||
|
||||
/* Make the call. */
|
||||
bctrl
|
||||
|
||||
/* This must follow the call immediately, the unwinder
|
||||
uses this to find out if r2 has been saved or not. */
|
||||
ld %r2, 40(%r1)
|
||||
|
||||
/* 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. */
|
||||
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)
|
||||
mtcrf 0x02, %r31 /* cr6 */
|
||||
bf 27, .Ldone_return_value
|
||||
stfd %f2, 8(%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,EH_FRAME_FLAGS,@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
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
236
src/powerpc/.svn/text-base/linux64_closure.S.svn-base
Normal file
236
src/powerpc/.svn/text-base/linux64_closure.S.svn-base
Normal file
@@ -0,0 +1,236 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@redhat.com>
|
||||
Copyright (c) 2008 Red Hat, Inc.
|
||||
|
||||
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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
.file "linux64_closure.S"
|
||||
|
||||
#ifdef __powerpc64__
|
||||
FFI_HIDDEN (ffi_closure_LINUX64)
|
||||
FFI_HIDDEN (.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
|
||||
# + 16 bytes retval area + 13*8 bytes fpr save area + round to 16
|
||||
stdu %r1, -240(%r1)
|
||||
.LCFI0:
|
||||
|
||||
# next save fpr 1 to fpr 13
|
||||
stfd %f1, 128+(0*8)(%r1)
|
||||
stfd %f2, 128+(1*8)(%r1)
|
||||
stfd %f3, 128+(2*8)(%r1)
|
||||
stfd %f4, 128+(3*8)(%r1)
|
||||
stfd %f5, 128+(4*8)(%r1)
|
||||
stfd %f6, 128+(5*8)(%r1)
|
||||
stfd %f7, 128+(6*8)(%r1)
|
||||
stfd %f8, 128+(7*8)(%r1)
|
||||
stfd %f9, 128+(8*8)(%r1)
|
||||
stfd %f10, 128+(9*8)(%r1)
|
||||
stfd %f11, 128+(10*8)(%r1)
|
||||
stfd %f12, 128+(11*8)(%r1)
|
||||
stfd %f13, 128+(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, 240 + 48
|
||||
|
||||
# now load up the pointer to the saved fpr registers */
|
||||
addi %r6, %r1, 128
|
||||
|
||||
# make the call
|
||||
bl .ffi_closure_helper_LINUX64
|
||||
.Lret:
|
||||
|
||||
# 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
|
||||
mflr %r4 # move address of .Lret to r4
|
||||
sldi %r3, %r3, 4 # now multiply return type by 16
|
||||
addi %r4, %r4, .Lret_type0 - .Lret
|
||||
ld %r0, 240+16(%r1)
|
||||
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
|
||||
|
||||
.Lret_type0:
|
||||
# case FFI_TYPE_VOID
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
nop
|
||||
# case FFI_TYPE_INT
|
||||
lwa %r3, 112+4(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
# case FFI_TYPE_FLOAT
|
||||
lfs %f1, 112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
# case FFI_TYPE_DOUBLE
|
||||
lfd %f1, 112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
# case FFI_TYPE_LONGDOUBLE
|
||||
lfd %f1, 112+0(%r1)
|
||||
mtlr %r0
|
||||
lfd %f2, 112+8(%r1)
|
||||
b .Lfinish
|
||||
# case FFI_TYPE_UINT8
|
||||
lbz %r3, 112+7(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
# case FFI_TYPE_SINT8
|
||||
lbz %r3, 112+7(%r1)
|
||||
extsb %r3,%r3
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
# case FFI_TYPE_UINT16
|
||||
lhz %r3, 112+6(%r1)
|
||||
mtlr %r0
|
||||
.Lfinish:
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
# case FFI_TYPE_SINT16
|
||||
lha %r3, 112+6(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
# case FFI_TYPE_UINT32
|
||||
lwz %r3, 112+4(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
# case FFI_TYPE_SINT32
|
||||
lwa %r3, 112+4(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
# case FFI_TYPE_UINT64
|
||||
ld %r3, 112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
# case FFI_TYPE_SINT64
|
||||
ld %r3, 112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
# case FFI_TYPE_STRUCT
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
nop
|
||||
# case FFI_TYPE_POINTER
|
||||
ld %r3, 112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
# esac
|
||||
.LFE1:
|
||||
.long 0
|
||||
.byte 0,12,0,1,128,0,0,0
|
||||
.size .ffi_closure_LINUX64,.-.ffi_closure_LINUX64
|
||||
|
||||
.section .eh_frame,EH_FRAME_FLAGS,@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 240
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x41
|
||||
.sleb128 -2
|
||||
.align 3
|
||||
.LEFDE1:
|
||||
#endif
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
327
src/powerpc/.svn/text-base/ppc_closure.S.svn-base
Normal file
327
src/powerpc/.svn/text-base/ppc_closure.S.svn-base
Normal file
@@ -0,0 +1,327 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@redhat.com>
|
||||
Copyright (c) 2008 Red Hat, Inc.
|
||||
|
||||
PowerPC 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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#include <powerpc/asm.h>
|
||||
|
||||
.file "ppc_closure.S"
|
||||
|
||||
#ifndef __powerpc64__
|
||||
|
||||
ENTRY(ffi_closure_SYSV)
|
||||
.LFB1:
|
||||
stwu %r1,-144(%r1)
|
||||
.LCFI0:
|
||||
mflr %r0
|
||||
.LCFI1:
|
||||
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)
|
||||
|
||||
#ifndef __NO_FPRS__
|
||||
# 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)
|
||||
#endif
|
||||
|
||||
# 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 ffi_closure_helper_SYSV@local
|
||||
.Lret:
|
||||
# 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
|
||||
|
||||
mflr %r4 # move address of .Lret to r4
|
||||
slwi %r3,%r3,4 # now multiply return type by 16
|
||||
addi %r4, %r4, .Lret_type0 - .Lret
|
||||
lwz %r0,148(%r1)
|
||||
add %r3,%r3,%r4 # add contents of table to table address
|
||||
mtctr %r3
|
||||
bctr # jump to it
|
||||
.LFE1:
|
||||
|
||||
# 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
|
||||
# case FFI_TYPE_VOID
|
||||
.Lret_type0:
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_INT
|
||||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
.Lfinish:
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_FLOAT
|
||||
lfs %f1,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_DOUBLE
|
||||
lfd %f1,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_LONGDOUBLE
|
||||
lfd %f1,112+0(%r1)
|
||||
lfd %f2,112+8(%r1)
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
|
||||
# case FFI_TYPE_UINT8
|
||||
lbz %r3,112+3(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_SINT8
|
||||
lbz %r3,112+3(%r1)
|
||||
extsb %r3,%r3
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
|
||||
# case FFI_TYPE_UINT16
|
||||
lhz %r3,112+2(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_SINT16
|
||||
lha %r3,112+2(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_UINT32
|
||||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_SINT32
|
||||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_UINT64
|
||||
lwz %r3,112+0(%r1)
|
||||
lwz %r4,112+4(%r1)
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
|
||||
# case FFI_TYPE_SINT64
|
||||
lwz %r3,112+0(%r1)
|
||||
lwz %r4,112+4(%r1)
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
|
||||
# case FFI_TYPE_STRUCT
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_POINTER
|
||||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_UINT128
|
||||
lwz %r3,112+0(%r1)
|
||||
lwz %r4,112+4(%r1)
|
||||
lwz %r5,112+8(%r1)
|
||||
bl .Luint128
|
||||
|
||||
# The return types below are only used when the ABI type is FFI_SYSV.
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct.
|
||||
lbz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
|
||||
lhz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
|
||||
lwz %r3,112+0(%r1)
|
||||
srwi %r3,%r3,8
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct.
|
||||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
|
||||
lwz %r3,112+0(%r1)
|
||||
lwz %r4,112+4(%r1)
|
||||
li %r5,24
|
||||
b .Lstruct567
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct.
|
||||
lwz %r3,112+0(%r1)
|
||||
lwz %r4,112+4(%r1)
|
||||
li %r5,16
|
||||
b .Lstruct567
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct.
|
||||
lwz %r3,112+0(%r1)
|
||||
lwz %r4,112+4(%r1)
|
||||
li %r5,8
|
||||
b .Lstruct567
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct.
|
||||
lwz %r3,112+0(%r1)
|
||||
lwz %r4,112+4(%r1)
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
|
||||
.Lstruct567:
|
||||
subfic %r6,%r5,32
|
||||
srw %r4,%r4,%r5
|
||||
slw %r6,%r3,%r6
|
||||
srw %r3,%r3,%r5
|
||||
or %r4,%r6,%r4
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
.Luint128:
|
||||
lwz %r6,112+12(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
END(ffi_closure_SYSV)
|
||||
|
||||
.section ".eh_frame",EH_FRAME_FLAGS,@progbits
|
||||
.Lframe1:
|
||||
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
|
||||
.LSCIE1:
|
||||
.4byte 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
#else
|
||||
.ascii "\0" # CIE Augmentation
|
||||
#endif
|
||||
.uleb128 0x1 # CIE Code Alignment Factor
|
||||
.sleb128 -4 # CIE Data Alignment Factor
|
||||
.byte 0x41 # CIE RA Column
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.uleb128 0x1 # Augmentation size
|
||||
.byte 0x1b # FDE Encoding (pcrel sdata4)
|
||||
#endif
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1
|
||||
.uleb128 0x0
|
||||
.align 2
|
||||
.LECIE1:
|
||||
.LSFDE1:
|
||||
.4byte .LEFDE1-.LASFDE1 # FDE Length
|
||||
.LASFDE1:
|
||||
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.4byte .LFB1-. # FDE initial location
|
||||
#else
|
||||
.4byte .LFB1 # FDE initial location
|
||||
#endif
|
||||
.4byte .LFE1-.LFB1 # FDE address range
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.uleb128 0x0 # Augmentation size
|
||||
#endif
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI0-.LFB1
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 144
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI1-.LCFI0
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x41
|
||||
.sleb128 -1
|
||||
.align 2
|
||||
.LEFDE1:
|
||||
|
||||
#endif
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
219
src/powerpc/.svn/text-base/sysv.S.svn-base
Normal file
219
src/powerpc/.svn/text-base/sysv.S.svn-base
Normal file
@@ -0,0 +1,219 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 1998 Geoffrey Keating
|
||||
Copyright (C) 2007 Free Software Foundation, Inc
|
||||
|
||||
PowerPC 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 AUTHORS OR COPYRIGHT
|
||||
HOLDERS 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#include <powerpc/asm.h>
|
||||
|
||||
#ifndef __powerpc64__
|
||||
.globl ffi_prep_args_SYSV
|
||||
ENTRY(ffi_call_SYSV)
|
||||
.LFB1:
|
||||
/* Save the old stack pointer as AP. */
|
||||
mr %r8,%r1
|
||||
|
||||
.LCFI0:
|
||||
/* Allocate the stack space we need. */
|
||||
stwux %r1,%r1,%r4
|
||||
/* Save registers we use. */
|
||||
mflr %r9
|
||||
stw %r28,-16(%r8)
|
||||
.LCFI1:
|
||||
stw %r29,-12(%r8)
|
||||
.LCFI2:
|
||||
stw %r30, -8(%r8)
|
||||
.LCFI3:
|
||||
stw %r31, -4(%r8)
|
||||
.LCFI4:
|
||||
stw %r9, 4(%r8)
|
||||
.LCFI5:
|
||||
|
||||
/* Save arguments over call... */
|
||||
mr %r31,%r5 /* flags, */
|
||||
mr %r30,%r6 /* rvalue, */
|
||||
mr %r29,%r7 /* function address, */
|
||||
mr %r28,%r8 /* our AP. */
|
||||
.LCFI6:
|
||||
|
||||
/* Call ffi_prep_args_SYSV. */
|
||||
mr %r4,%r1
|
||||
bl ffi_prep_args_SYSV@local
|
||||
|
||||
/* 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 %r29
|
||||
/* Load all those argument registers. */
|
||||
lwz %r3,-16-(8*4)(%r28)
|
||||
lwz %r4,-16-(7*4)(%r28)
|
||||
lwz %r5,-16-(6*4)(%r28)
|
||||
lwz %r6,-16-(5*4)(%r28)
|
||||
bf- 5,1f
|
||||
nop
|
||||
lwz %r7,-16-(4*4)(%r28)
|
||||
lwz %r8,-16-(3*4)(%r28)
|
||||
lwz %r9,-16-(2*4)(%r28)
|
||||
lwz %r10,-16-(1*4)(%r28)
|
||||
nop
|
||||
1:
|
||||
|
||||
/* Load all the FP registers. */
|
||||
bf- 6,2f
|
||||
lfd %f1,-16-(8*4)-(8*8)(%r28)
|
||||
lfd %f2,-16-(8*4)-(7*8)(%r28)
|
||||
lfd %f3,-16-(8*4)-(6*8)(%r28)
|
||||
lfd %f4,-16-(8*4)-(5*8)(%r28)
|
||||
nop
|
||||
lfd %f5,-16-(8*4)-(4*8)(%r28)
|
||||
lfd %f6,-16-(8*4)-(3*8)(%r28)
|
||||
lfd %f7,-16-(8*4)-(2*8)(%r28)
|
||||
lfd %f8,-16-(8*4)-(1*8)(%r28)
|
||||
2:
|
||||
|
||||
/* Make the call. */
|
||||
bctrl
|
||||
|
||||
/* Now, deal with the return value. */
|
||||
mtcrf 0x01,%r31 /* cr7 */
|
||||
bt- 31,L(small_struct_return_value)
|
||||
bt- 30,L(done_return_value)
|
||||
bt- 29,L(fp_return_value)
|
||||
stw %r3,0(%r30)
|
||||
bf+ 28,L(done_return_value)
|
||||
stw %r4,4(%r30)
|
||||
mtcrf 0x02,%r31 /* cr6 */
|
||||
bf 27,L(done_return_value)
|
||||
stw %r5,8(%r30)
|
||||
stw %r6,12(%r30)
|
||||
/* Fall through... */
|
||||
|
||||
L(done_return_value):
|
||||
/* Restore the registers we used and return. */
|
||||
lwz %r9, 4(%r28)
|
||||
lwz %r31, -4(%r28)
|
||||
mtlr %r9
|
||||
lwz %r30, -8(%r28)
|
||||
lwz %r29,-12(%r28)
|
||||
lwz %r28,-16(%r28)
|
||||
lwz %r1,0(%r1)
|
||||
blr
|
||||
|
||||
L(fp_return_value):
|
||||
bf 28,L(float_return_value)
|
||||
stfd %f1,0(%r30)
|
||||
mtcrf 0x02,%r31 /* cr6 */
|
||||
bf 27,L(done_return_value)
|
||||
stfd %f2,8(%r30)
|
||||
b L(done_return_value)
|
||||
L(float_return_value):
|
||||
stfs %f1,0(%r30)
|
||||
b L(done_return_value)
|
||||
|
||||
L(small_struct_return_value):
|
||||
extrwi %r6,%r31,2,19 /* number of bytes padding = shift/8 */
|
||||
mtcrf 0x02,%r31 /* copy flags to cr[24:27] (cr6) */
|
||||
extrwi %r5,%r31,5,19 /* r5 <- number of bits of padding */
|
||||
subfic %r6,%r6,4 /* r6 <- number of useful bytes in r3 */
|
||||
bf- 25,L(done_return_value) /* struct in r3 ? if not, done. */
|
||||
/* smst_one_register: */
|
||||
slw %r3,%r3,%r5 /* Left-justify value in r3 */
|
||||
mtxer %r6 /* move byte count to XER ... */
|
||||
stswx %r3,0,%r30 /* ... and store that many bytes */
|
||||
bf+ 26,L(done_return_value) /* struct in r3:r4 ? */
|
||||
add %r6,%r6,%r30 /* adjust pointer */
|
||||
stswi %r4,%r6,4 /* store last four bytes */
|
||||
b L(done_return_value)
|
||||
|
||||
.LFE1:
|
||||
END(ffi_call_SYSV)
|
||||
|
||||
.section ".eh_frame",EH_FRAME_FLAGS,@progbits
|
||||
.Lframe1:
|
||||
.4byte .LECIE1-.LSCIE1 /* Length of Common Information Entry */
|
||||
.LSCIE1:
|
||||
.4byte 0x0 /* CIE Identifier Tag */
|
||||
.byte 0x1 /* CIE Version */
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.ascii "zR\0" /* CIE Augmentation */
|
||||
#else
|
||||
.ascii "\0" /* CIE Augmentation */
|
||||
#endif
|
||||
.uleb128 0x1 /* CIE Code Alignment Factor */
|
||||
.sleb128 -4 /* CIE Data Alignment Factor */
|
||||
.byte 0x41 /* CIE RA Column */
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.uleb128 0x1 /* Augmentation size */
|
||||
.byte 0x1b /* FDE Encoding (pcrel sdata4) */
|
||||
#endif
|
||||
.byte 0xc /* DW_CFA_def_cfa */
|
||||
.uleb128 0x1
|
||||
.uleb128 0x0
|
||||
.align 2
|
||||
.LECIE1:
|
||||
.LSFDE1:
|
||||
.4byte .LEFDE1-.LASFDE1 /* FDE Length */
|
||||
.LASFDE1:
|
||||
.4byte .LASFDE1-.Lframe1 /* FDE CIE offset */
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.4byte .LFB1-. /* FDE initial location */
|
||||
#else
|
||||
.4byte .LFB1 /* FDE initial location */
|
||||
#endif
|
||||
.4byte .LFE1-.LFB1 /* FDE address range */
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.uleb128 0x0 /* Augmentation size */
|
||||
#endif
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFI0-.LFB1
|
||||
.byte 0xd /* DW_CFA_def_cfa_register */
|
||||
.uleb128 0x08
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFI5-.LCFI0
|
||||
.byte 0x11 /* DW_CFA_offset_extended_sf */
|
||||
.uleb128 0x41
|
||||
.sleb128 -1
|
||||
.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
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFI6-.LCFI5
|
||||
.byte 0xd /* DW_CFA_def_cfa_register */
|
||||
.uleb128 0x1c
|
||||
.align 2
|
||||
.LEFDE1:
|
||||
#endif
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
225
src/powerpc/aix.S
Normal file
225
src/powerpc/aix.S
Normal file
@@ -0,0 +1,225 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
aix.S - Copyright (c) 2002 Free Software Foundation, Inc.
|
||||
based on darwin.S by John Hornkvist
|
||||
|
||||
PowerPC 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
.set r0,0
|
||||
.set r1,1
|
||||
.set r2,2
|
||||
.set r3,3
|
||||
.set r4,4
|
||||
.set r5,5
|
||||
.set r6,6
|
||||
.set r7,7
|
||||
.set r8,8
|
||||
.set r9,9
|
||||
.set r10,10
|
||||
.set r11,11
|
||||
.set r12,12
|
||||
.set r13,13
|
||||
.set r14,14
|
||||
.set r15,15
|
||||
.set r16,16
|
||||
.set r17,17
|
||||
.set r18,18
|
||||
.set r19,19
|
||||
.set r20,20
|
||||
.set r21,21
|
||||
.set r22,22
|
||||
.set r23,23
|
||||
.set r24,24
|
||||
.set r25,25
|
||||
.set r26,26
|
||||
.set r27,27
|
||||
.set r28,28
|
||||
.set r29,29
|
||||
.set r30,30
|
||||
.set r31,31
|
||||
.set f0,0
|
||||
.set f1,1
|
||||
.set f2,2
|
||||
.set f3,3
|
||||
.set f4,4
|
||||
.set f5,5
|
||||
.set f6,6
|
||||
.set f7,7
|
||||
.set f8,8
|
||||
.set f9,9
|
||||
.set f10,10
|
||||
.set f11,11
|
||||
.set f12,12
|
||||
.set f13,13
|
||||
.set f14,14
|
||||
.set f15,15
|
||||
.set f16,16
|
||||
.set f17,17
|
||||
.set f18,18
|
||||
.set f19,19
|
||||
.set f20,20
|
||||
.set f21,21
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#define JUMPTARGET(name) name
|
||||
#define L(x) x
|
||||
.file "aix.S"
|
||||
.toc
|
||||
.csect .text[PR]
|
||||
.align 2
|
||||
.globl ffi_prep_args
|
||||
|
||||
.csect .text[PR]
|
||||
.align 2
|
||||
.globl ffi_call_AIX
|
||||
.globl .ffi_call_AIX
|
||||
.csect ffi_call_AIX[DS]
|
||||
ffi_call_AIX:
|
||||
.long .ffi_call_AIX, TOC[tc0], 0
|
||||
.csect .text[PR]
|
||||
.ffi_call_AIX:
|
||||
mr r12,r8 // We only need r12 until the call, so it doesn't have to be saved...
|
||||
/* Save the old stack pointer as AP. */
|
||||
mr r8,r1
|
||||
|
||||
/* Allocate the stack space we need. */
|
||||
stwux r1,r1,r4
|
||||
|
||||
/* Save registers we use. */
|
||||
mflr r9
|
||||
|
||||
stw r28,-16(r8)
|
||||
stw r29,-12(r8)
|
||||
stw r30, -8(r8)
|
||||
stw r31, -4(r8)
|
||||
|
||||
stw r9, 8(r8)
|
||||
stw r2, 20(r1)
|
||||
|
||||
/* Save arguments over call... */
|
||||
mr r31,r5 /* flags, */
|
||||
mr r30,r6 /* rvalue, */
|
||||
mr r29,r7 /* function address, */
|
||||
mr r28,r8 /* our AP. */
|
||||
|
||||
/* Call ffi_prep_args. */
|
||||
mr r4,r1
|
||||
li r9,0
|
||||
|
||||
lwz r2,4(r12)
|
||||
lwz r12,0(r12)
|
||||
mtctr r12 // r12 holds address of _ffi_prep_args
|
||||
bctrl
|
||||
lwz r2,20(r1)
|
||||
|
||||
/* Now do the call. */
|
||||
lwz r12,0(r29)
|
||||
/* Set up cr1 with bits 4-7 of the flags. */
|
||||
mtcrf 0x40,r31
|
||||
stw r2,20(r1)
|
||||
mtctr r12
|
||||
lwz r2,4(r29)
|
||||
/* Load all those argument registers. */
|
||||
// We have set up a nice stack frame, just load it into registers.
|
||||
lwz r3, 20+(1*4)(r1)
|
||||
lwz r4, 20+(2*4)(r1)
|
||||
lwz r5, 20+(3*4)(r1)
|
||||
lwz r6, 20+(4*4)(r1)
|
||||
nop
|
||||
lwz r7, 20+(5*4)(r1)
|
||||
lwz r8, 20+(6*4)(r1)
|
||||
lwz r9, 20+(7*4)(r1)
|
||||
lwz r10,20+(8*4)(r1)
|
||||
|
||||
L1:
|
||||
/* Load all the FP registers. */
|
||||
bf 6,L2 // 2f + 0x18
|
||||
lfd f1,-16-(13*8)(r28)
|
||||
lfd f2,-16-(12*8)(r28)
|
||||
lfd f3,-16-(11*8)(r28)
|
||||
lfd f4,-16-(10*8)(r28)
|
||||
nop
|
||||
lfd f5,-16-(9*8)(r28)
|
||||
lfd f6,-16-(8*8)(r28)
|
||||
lfd f7,-16-(7*8)(r28)
|
||||
lfd f8,-16-(6*8)(r28)
|
||||
nop
|
||||
lfd f9,-16-(5*8)(r28)
|
||||
lfd f10,-16-(4*8)(r28)
|
||||
lfd f11,-16-(3*8)(r28)
|
||||
lfd f12,-16-(2*8)(r28)
|
||||
nop
|
||||
lfd f13,-16-(1*8)(r28)
|
||||
|
||||
L2:
|
||||
/* Make the call. */
|
||||
bctrl
|
||||
lwz r2,20(r1)
|
||||
|
||||
/* Now, deal with the return value. */
|
||||
mtcrf 0x01,r31
|
||||
|
||||
bt 30,L(done_return_value)
|
||||
bt 29,L(fp_return_value)
|
||||
stw r3,0(r30)
|
||||
bf 28,L(done_return_value)
|
||||
stw r4,4(r30)
|
||||
|
||||
/* Fall through... */
|
||||
|
||||
L(done_return_value):
|
||||
/* Restore the registers we used and return. */
|
||||
lwz r9, 8(r28)
|
||||
lwz r31, -4(r28)
|
||||
mtlr r9
|
||||
lwz r30, -8(r28)
|
||||
lwz r29,-12(r28)
|
||||
lwz r28,-16(r28)
|
||||
lwz r1,0(r1)
|
||||
blr
|
||||
|
||||
L(fp_return_value):
|
||||
bf 28,L(float_return_value)
|
||||
stfd f1,0(r30)
|
||||
b L(done_return_value)
|
||||
L(float_return_value):
|
||||
stfs f1,0(r30)
|
||||
b L(done_return_value)
|
||||
.long 0
|
||||
.byte 0,0,0,1,128,4,0,0
|
||||
//END(ffi_call_AIX)
|
||||
|
||||
.csect .text[PR]
|
||||
.align 2
|
||||
.globl ffi_call_DARWIN
|
||||
.globl .ffi_call_DARWIN
|
||||
.csect ffi_call_DARWIN[DS]
|
||||
ffi_call_DARWIN:
|
||||
.long .ffi_call_DARWIN, TOC[tc0], 0
|
||||
.csect .text[PR]
|
||||
.ffi_call_DARWIN:
|
||||
blr
|
||||
.long 0
|
||||
.byte 0,0,0,0,0,0,0,0
|
||||
//END(ffi_call_DARWIN)
|
||||
247
src/powerpc/aix_closure.S
Normal file
247
src/powerpc/aix_closure.S
Normal file
@@ -0,0 +1,247 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
aix_closure.S - Copyright (c) 2002 2003 Free Software Foundation, Inc.
|
||||
based on darwin_closure.S
|
||||
|
||||
PowerPC 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
.set r0,0
|
||||
.set r1,1
|
||||
.set r2,2
|
||||
.set r3,3
|
||||
.set r4,4
|
||||
.set r5,5
|
||||
.set r6,6
|
||||
.set r7,7
|
||||
.set r8,8
|
||||
.set r9,9
|
||||
.set r10,10
|
||||
.set r11,11
|
||||
.set r12,12
|
||||
.set r13,13
|
||||
.set r14,14
|
||||
.set r15,15
|
||||
.set r16,16
|
||||
.set r17,17
|
||||
.set r18,18
|
||||
.set r19,19
|
||||
.set r20,20
|
||||
.set r21,21
|
||||
.set r22,22
|
||||
.set r23,23
|
||||
.set r24,24
|
||||
.set r25,25
|
||||
.set r26,26
|
||||
.set r27,27
|
||||
.set r28,28
|
||||
.set r29,29
|
||||
.set r30,30
|
||||
.set r31,31
|
||||
.set f0,0
|
||||
.set f1,1
|
||||
.set f2,2
|
||||
.set f3,3
|
||||
.set f4,4
|
||||
.set f5,5
|
||||
.set f6,6
|
||||
.set f7,7
|
||||
.set f8,8
|
||||
.set f9,9
|
||||
.set f10,10
|
||||
.set f11,11
|
||||
.set f12,12
|
||||
.set f13,13
|
||||
.set f14,14
|
||||
.set f15,15
|
||||
.set f16,16
|
||||
.set f17,17
|
||||
.set f18,18
|
||||
.set f19,19
|
||||
.set f20,20
|
||||
.set f21,21
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#define JUMPTARGET(name) name
|
||||
#define L(x) x
|
||||
.file "aix_closure.S"
|
||||
.toc
|
||||
LC..60:
|
||||
.tc L..60[TC],L..60
|
||||
.csect .text[PR]
|
||||
.align 2
|
||||
|
||||
.csect .text[PR]
|
||||
.align 2
|
||||
.globl ffi_closure_ASM
|
||||
.globl .ffi_closure_ASM
|
||||
.csect ffi_closure_ASM[DS]
|
||||
|
||||
ffi_closure_ASM:
|
||||
.long .ffi_closure_ASM, TOC[tc0], 0
|
||||
.csect .text[PR]
|
||||
.ffi_closure_ASM:
|
||||
|
||||
mflr r0 /* extract return address */
|
||||
stw r0, 8(r1) /* save the return address */
|
||||
|
||||
/* 24 Bytes (Linkage Area) */
|
||||
/* 32 Bytes (params) */
|
||||
/* 104 Bytes (13*8 from FPR) */
|
||||
/* 8 Bytes (result) */
|
||||
/* 168 Bytes */
|
||||
|
||||
stwu r1,-176(r1) /* skip over caller save area
|
||||
keep stack aligned to 16 */
|
||||
|
||||
/* we want to build up an area for the parameters passed */
|
||||
/* in registers (both floating point and integer) */
|
||||
|
||||
/* we store gpr 3 to gpr 10 (aligned to 4)
|
||||
in the parents outgoing area */
|
||||
stw r3, 200(r1)
|
||||
stw r4, 204(r1)
|
||||
stw r5, 208(r1)
|
||||
stw r6, 212(r1)
|
||||
stw r7, 216(r1)
|
||||
stw r8, 220(r1)
|
||||
stw r9, 224(r1)
|
||||
stw r10, 228(r1)
|
||||
|
||||
/* next save fpr 1 to fpr 13 (aligned to 8) */
|
||||
stfd f1, 56(r1)
|
||||
stfd f2, 64(r1)
|
||||
stfd f3, 72(r1)
|
||||
stfd f4, 80(r1)
|
||||
stfd f5, 88(r1)
|
||||
stfd f6, 96(r1)
|
||||
stfd f7, 104(r1)
|
||||
stfd f8, 112(r1)
|
||||
stfd f9, 120(r1)
|
||||
stfd f10, 128(r1)
|
||||
stfd f11, 136(r1)
|
||||
stfd f12, 144(r1)
|
||||
stfd f13, 152(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,160
|
||||
|
||||
/* now load up the pointer to the saved gpr registers */
|
||||
addi r5,r1,200
|
||||
|
||||
/* now load up the pointer to the saved fpr registers */
|
||||
addi r6,r1,56
|
||||
|
||||
/* make the call */
|
||||
bl .ffi_closure_helper_DARWIN
|
||||
nop
|
||||
|
||||
/* 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,160 /* get pointer to results area */
|
||||
lwz r4,LC..60(2) /* get address of jump table */
|
||||
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 */
|
||||
|
||||
L..60:
|
||||
.long L..44-L..60 /* FFI_TYPE_VOID */
|
||||
.long L..50-L..60 /* FFI_TYPE_INT */
|
||||
.long L..47-L..60 /* FFI_TYPE_FLOAT */
|
||||
.long L..46-L..60 /* FFI_TYPE_DOUBLE */
|
||||
.long L..46-L..60 /* FFI_TYPE_LONGDOUBLE */
|
||||
.long L..56-L..60 /* FFI_TYPE_UINT8 */
|
||||
.long L..55-L..60 /* FFI_TYPE_SINT8 */
|
||||
.long L..58-L..60 /* FFI_TYPE_UINT16 */
|
||||
.long L..57-L..60 /* FFI_TYPE_SINT16 */
|
||||
.long L..50-L..60 /* FFI_TYPE_UINT32 */
|
||||
.long L..50-L..60 /* FFI_TYPE_SINT32 */
|
||||
.long L..48-L..60 /* FFI_TYPE_UINT64 */
|
||||
.long L..48-L..60 /* FFI_TYPE_SINT64 */
|
||||
.long L..44-L..60 /* FFI_TYPE_STRUCT */
|
||||
.long L..50-L..60 /* FFI_TYPE_POINTER */
|
||||
|
||||
|
||||
/* case double */
|
||||
L..46:
|
||||
lfd f1,0(r5)
|
||||
b L..44
|
||||
|
||||
/* case float */
|
||||
L..47:
|
||||
lfs f1,0(r5)
|
||||
b L..44
|
||||
|
||||
/* case long long */
|
||||
L..48:
|
||||
lwz r3,0(r5)
|
||||
lwz r4,4(r5)
|
||||
b L..44
|
||||
|
||||
/* case default / int32 / pointer */
|
||||
L..50:
|
||||
lwz r3,0(r5)
|
||||
b L..44
|
||||
|
||||
/* case signed int8 */
|
||||
L..55:
|
||||
addi r5,r5,3
|
||||
lbz r3,0(r5)
|
||||
slwi r3,r3,24
|
||||
srawi r3,r3,24
|
||||
b L..44
|
||||
|
||||
/* case unsigned int8 */
|
||||
L..56:
|
||||
addi r5,r5,3
|
||||
lbz r3,0(r5)
|
||||
b L..44
|
||||
|
||||
/* case signed int16 */
|
||||
L..57:
|
||||
addi r5,r5,2
|
||||
lhz r3,0(r5)
|
||||
extsh r3,r3
|
||||
b L..44
|
||||
|
||||
/* case unsigned int16 */
|
||||
L..58:
|
||||
addi r5,r5,2
|
||||
lhz r3,0(r5)
|
||||
|
||||
/* case void / done */
|
||||
L..44:
|
||||
addi r1,r1,176 /* restore stack pointer */
|
||||
lwz r0,8(r1) /* get return address */
|
||||
mtlr r0 /* reset link register */
|
||||
blr
|
||||
|
||||
/* END(ffi_closure_ASM) */
|
||||
125
src/powerpc/asm.h
Normal file
125
src/powerpc/asm.h
Normal file
@@ -0,0 +1,125 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
asm.h - Copyright (c) 1998 Geoffrey Keating
|
||||
|
||||
PowerPC 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 ASM_GLOBAL_DIRECTIVE .globl
|
||||
|
||||
|
||||
#define C_SYMBOL_NAME(name) name
|
||||
/* Macro for a label. */
|
||||
#ifdef __STDC__
|
||||
#define C_LABEL(name) name##:
|
||||
#else
|
||||
#define C_LABEL(name) name/**/:
|
||||
#endif
|
||||
|
||||
/* This seems to always be the case on PPC. */
|
||||
#define ALIGNARG(log2) log2
|
||||
/* For ELF we need the `.type' directive to make shared libs work right. */
|
||||
#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg;
|
||||
#define ASM_SIZE_DIRECTIVE(name) .size name,.-name
|
||||
|
||||
/* If compiled for profiling, call `_mcount' at the start of each function. */
|
||||
#ifdef PROF
|
||||
/* The mcount code relies on a the return address being on the stack
|
||||
to locate our caller and so it can restore it; so store one just
|
||||
for its benefit. */
|
||||
#ifdef PIC
|
||||
#define CALL_MCOUNT \
|
||||
.pushsection; \
|
||||
.section ".data"; \
|
||||
.align ALIGNARG(2); \
|
||||
0:.long 0; \
|
||||
.previous; \
|
||||
mflr %r0; \
|
||||
stw %r0,4(%r1); \
|
||||
bl _GLOBAL_OFFSET_TABLE_@local-4; \
|
||||
mflr %r11; \
|
||||
lwz %r0,0b@got(%r11); \
|
||||
bl JUMPTARGET(_mcount);
|
||||
#else /* PIC */
|
||||
#define CALL_MCOUNT \
|
||||
.section ".data"; \
|
||||
.align ALIGNARG(2); \
|
||||
0:.long 0; \
|
||||
.previous; \
|
||||
mflr %r0; \
|
||||
lis %r11,0b@ha; \
|
||||
stw %r0,4(%r1); \
|
||||
addi %r0,%r11,0b@l; \
|
||||
bl JUMPTARGET(_mcount);
|
||||
#endif /* PIC */
|
||||
#else /* PROF */
|
||||
#define CALL_MCOUNT /* Do nothing. */
|
||||
#endif /* PROF */
|
||||
|
||||
#define ENTRY(name) \
|
||||
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \
|
||||
ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \
|
||||
.align ALIGNARG(2); \
|
||||
C_LABEL(name) \
|
||||
CALL_MCOUNT
|
||||
|
||||
#define EALIGN_W_0 /* No words to insert. */
|
||||
#define EALIGN_W_1 nop
|
||||
#define EALIGN_W_2 nop;nop
|
||||
#define EALIGN_W_3 nop;nop;nop
|
||||
#define EALIGN_W_4 EALIGN_W_3;nop
|
||||
#define EALIGN_W_5 EALIGN_W_4;nop
|
||||
#define EALIGN_W_6 EALIGN_W_5;nop
|
||||
#define EALIGN_W_7 EALIGN_W_6;nop
|
||||
|
||||
/* EALIGN is like ENTRY, but does alignment to 'words'*4 bytes
|
||||
past a 2^align boundary. */
|
||||
#ifdef PROF
|
||||
#define EALIGN(name, alignt, words) \
|
||||
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \
|
||||
ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \
|
||||
.align ALIGNARG(2); \
|
||||
C_LABEL(name) \
|
||||
CALL_MCOUNT \
|
||||
b 0f; \
|
||||
.align ALIGNARG(alignt); \
|
||||
EALIGN_W_##words; \
|
||||
0:
|
||||
#else /* PROF */
|
||||
#define EALIGN(name, alignt, words) \
|
||||
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \
|
||||
ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \
|
||||
.align ALIGNARG(alignt); \
|
||||
EALIGN_W_##words; \
|
||||
C_LABEL(name)
|
||||
#endif
|
||||
|
||||
#define END(name) \
|
||||
ASM_SIZE_DIRECTIVE(name)
|
||||
|
||||
#ifdef PIC
|
||||
#define JUMPTARGET(name) name##@plt
|
||||
#else
|
||||
#define JUMPTARGET(name) name
|
||||
#endif
|
||||
|
||||
/* Local labels stripped out by the linker. */
|
||||
#define L(x) .L##x
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user