mirror of
https://github.com/partic2/libffi
synced 2026-11-10 18:17:19 +00:00
Rebase
This commit is contained in:
@@ -1,130 +0,0 @@
|
||||
10
|
||||
|
||||
dir
|
||||
161959
|
||||
svn://gcc.gnu.org/svn/gcc/trunk/libffi/src/sh64
|
||||
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
|
||||
86900415ba310dc614e41339d057ebc2
|
||||
2009-06-04T15:11:12.475454Z
|
||||
148171
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1933
|
||||
|
||||
ffi.c
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:01.000000Z
|
||||
eb58c57943b4ed8a754ad8a673eab931
|
||||
2009-06-04T15:43:03.499507Z
|
||||
148172
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
11287
|
||||
|
||||
sysv.S
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2009-06-10T05:25:01.000000Z
|
||||
981772e8eedf7ba19049819909040d94
|
||||
2009-06-04T15:11:12.475454Z
|
||||
148171
|
||||
aph
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
11693
|
||||
|
||||
@@ -1,468 +0,0 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2003, 2004, 2006, 2007 Kaz Kojima
|
||||
Copyright (c) 2008 Anthony Green
|
||||
|
||||
SuperH SHmedia 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>
|
||||
|
||||
#define NGREGARG 8
|
||||
#define NFREGARG 12
|
||||
|
||||
static int
|
||||
return_type (ffi_type *arg)
|
||||
{
|
||||
|
||||
if (arg->type != FFI_TYPE_STRUCT)
|
||||
return arg->type;
|
||||
|
||||
/* gcc uses r2 if the result can be packed in on register. */
|
||||
if (arg->size <= sizeof (UINT8))
|
||||
return FFI_TYPE_UINT8;
|
||||
else if (arg->size <= sizeof (UINT16))
|
||||
return FFI_TYPE_UINT16;
|
||||
else if (arg->size <= sizeof (UINT32))
|
||||
return FFI_TYPE_UINT32;
|
||||
else if (arg->size <= sizeof (UINT64))
|
||||
return FFI_TYPE_UINT64;
|
||||
|
||||
return FFI_TYPE_STRUCT;
|
||||
}
|
||||
|
||||
/* 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 unsigned int avn;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
|
||||
argp = stack;
|
||||
|
||||
if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
|
||||
{
|
||||
*(void **) argp = ecif->rvalue;
|
||||
argp += sizeof (UINT64);
|
||||
}
|
||||
|
||||
avn = ecif->cif->nargs;
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
|
||||
{
|
||||
size_t z;
|
||||
int align;
|
||||
|
||||
z = (*p_arg)->size;
|
||||
align = (*p_arg)->alignment;
|
||||
if (z < sizeof (UINT32))
|
||||
{
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(SINT64 *) argp = (SINT64) *(SINT8 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(UINT64 *) argp = (UINT64) *(UINT8 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(SINT64 *) argp = (SINT64) *(SINT16 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(UINT64 *) argp = (UINT64) *(UINT16 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
memcpy (argp, *p_argv, z);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
argp += sizeof (UINT64);
|
||||
}
|
||||
else if (z == sizeof (UINT32) && align == sizeof (UINT32))
|
||||
{
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_SINT32:
|
||||
*(SINT64 *) argp = (SINT64) *(SINT32 *) (*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_POINTER:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_STRUCT:
|
||||
*(UINT64 *) argp = (UINT64) *(UINT32 *) (*p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
argp += sizeof (UINT64);
|
||||
}
|
||||
else if (z == sizeof (UINT64)
|
||||
&& align == sizeof (UINT64)
|
||||
&& ((int) *p_argv & (sizeof (UINT64) - 1)) == 0)
|
||||
{
|
||||
*(UINT64 *) argp = *(UINT64 *) (*p_argv);
|
||||
argp += sizeof (UINT64);
|
||||
}
|
||||
else
|
||||
{
|
||||
int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64);
|
||||
|
||||
memcpy (argp, *p_argv, z);
|
||||
argp += n * sizeof (UINT64);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
int i, j;
|
||||
int size, type;
|
||||
int n, m;
|
||||
int greg;
|
||||
int freg;
|
||||
int fpair = -1;
|
||||
|
||||
greg = (return_type (cif->rtype) == FFI_TYPE_STRUCT ? 1 : 0);
|
||||
freg = 0;
|
||||
cif->flags2 = 0;
|
||||
|
||||
for (i = j = 0; i < cif->nargs; i++)
|
||||
{
|
||||
type = (cif->arg_types)[i]->type;
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_FLOAT:
|
||||
greg++;
|
||||
cif->bytes += sizeof (UINT64) - sizeof (float);
|
||||
if (freg >= NFREGARG - 1)
|
||||
continue;
|
||||
if (fpair < 0)
|
||||
{
|
||||
fpair = freg;
|
||||
freg += 2;
|
||||
}
|
||||
else
|
||||
fpair = -1;
|
||||
cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
if (greg++ >= NGREGARG && (freg + 1) >= NFREGARG)
|
||||
continue;
|
||||
if ((freg + 1) < NFREGARG)
|
||||
{
|
||||
freg += 2;
|
||||
cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
|
||||
}
|
||||
else
|
||||
cif->flags2 += FFI_TYPE_INT << (2 * j++);
|
||||
break;
|
||||
|
||||
default:
|
||||
size = (cif->arg_types)[i]->size;
|
||||
if (size < sizeof (UINT64))
|
||||
cif->bytes += sizeof (UINT64) - size;
|
||||
n = (size + sizeof (UINT64) - 1) / sizeof (UINT64);
|
||||
if (greg >= NGREGARG)
|
||||
continue;
|
||||
else if (greg + n - 1 >= NGREGARG)
|
||||
greg = NGREGARG;
|
||||
else
|
||||
greg += n;
|
||||
for (m = 0; m < n; m++)
|
||||
cif->flags2 += FFI_TYPE_INT << (2 * j++);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_STRUCT:
|
||||
cif->flags = return_type (cif->rtype);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
cif->flags = cif->rtype->type;
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/*@-declundef@*/
|
||||
/*@-exportheader@*/
|
||||
extern void ffi_call_SYSV(void (*)(char *, extended_cif *),
|
||||
/*@out@*/ extended_cif *,
|
||||
unsigned, unsigned, long long,
|
||||
/*@out@*/ unsigned *,
|
||||
void (*fn)(void));
|
||||
/*@=declundef@*/
|
||||
/*@=exportheader@*/
|
||||
|
||||
void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(void),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
UINT64 trvalue;
|
||||
|
||||
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 (cif->rtype->type == FFI_TYPE_STRUCT
|
||||
&& return_type (cif->rtype) != FFI_TYPE_STRUCT)
|
||||
ecif.rvalue = &trvalue;
|
||||
else 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, cif->flags2,
|
||||
ecif.rvalue, fn);
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (rvalue
|
||||
&& cif->rtype->type == FFI_TYPE_STRUCT
|
||||
&& return_type (cif->rtype) != FFI_TYPE_STRUCT)
|
||||
memcpy (rvalue, &trvalue, cif->rtype->size);
|
||||
}
|
||||
|
||||
extern void ffi_closure_SYSV (void);
|
||||
extern void __ic_invalidate (void *line);
|
||||
|
||||
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;
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
|
||||
|
||||
tramp = (unsigned int *) &closure->tramp[0];
|
||||
/* Since ffi_closure is an aligned object, the ffi trampoline is
|
||||
called as an SHcompact code. Sigh.
|
||||
SHcompact part:
|
||||
mova @(1,pc),r0; add #1,r0; jmp @r0; nop;
|
||||
SHmedia part:
|
||||
movi fnaddr >> 16,r1; shori fnaddr,r1; ptabs/l r1,tr0
|
||||
movi cxt >> 16,r1; shori cxt,r1; blink tr0,r63 */
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
tramp[0] = 0x7001c701;
|
||||
tramp[1] = 0x0009402b;
|
||||
#else
|
||||
tramp[0] = 0xc7017001;
|
||||
tramp[1] = 0x402b0009;
|
||||
#endif
|
||||
tramp[2] = 0xcc000010 | (((UINT32) ffi_closure_SYSV) >> 16) << 10;
|
||||
tramp[3] = 0xc8000010 | (((UINT32) ffi_closure_SYSV) & 0xffff) << 10;
|
||||
tramp[4] = 0x6bf10600;
|
||||
tramp[5] = 0xcc000010 | (((UINT32) codeloc) >> 16) << 10;
|
||||
tramp[6] = 0xc8000010 | (((UINT32) codeloc) & 0xffff) << 10;
|
||||
tramp[7] = 0x4401fff0;
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
/* Flush the icache. */
|
||||
asm volatile ("ocbwb %0,0; synco; icbi %1,0; synci" : : "r" (tramp),
|
||||
"r"(codeloc));
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/* Basically the trampoline invokes ffi_closure_SYSV, and on
|
||||
* entry, r3 holds the address of the closure.
|
||||
* After storing the registers that could possibly contain
|
||||
* parameters to be passed into the stack frame and setting
|
||||
* up space for a return value, ffi_closure_SYSV invokes the
|
||||
* following helper function to do most of the work.
|
||||
*/
|
||||
|
||||
int
|
||||
ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue,
|
||||
UINT64 *pgr, UINT64 *pfr, UINT64 *pst)
|
||||
{
|
||||
void **avalue;
|
||||
ffi_type **p_arg;
|
||||
int i, avn;
|
||||
int greg, freg;
|
||||
ffi_cif *cif;
|
||||
int fpair = -1;
|
||||
|
||||
cif = closure->cif;
|
||||
avalue = alloca (cif->nargs * sizeof (void *));
|
||||
|
||||
/* Copy the caller's structure return value address so that the closure
|
||||
returns the data directly to the caller. */
|
||||
if (return_type (cif->rtype) == FFI_TYPE_STRUCT)
|
||||
{
|
||||
rvalue = (UINT64 *) *pgr;
|
||||
greg = 1;
|
||||
}
|
||||
else
|
||||
greg = 0;
|
||||
|
||||
freg = 0;
|
||||
cif = closure->cif;
|
||||
avn = cif->nargs;
|
||||
|
||||
/* Grab the addresses of the arguments from the stack frame. */
|
||||
for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
void *p;
|
||||
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof (UINT32))
|
||||
{
|
||||
p = pgr + greg++;
|
||||
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_STRUCT:
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
avalue[i] = p;
|
||||
#else
|
||||
avalue[i] = ((char *) p) + sizeof (UINT32) - z;
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
}
|
||||
else if (z == sizeof (UINT32))
|
||||
{
|
||||
if ((*p_arg)->type == FFI_TYPE_FLOAT)
|
||||
{
|
||||
if (freg < NFREGARG - 1)
|
||||
{
|
||||
if (fpair >= 0)
|
||||
{
|
||||
avalue[i] = (UINT32 *) pfr + fpair;
|
||||
fpair = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
fpair = freg;
|
||||
avalue[i] = (UINT32 *) pfr + (1 ^ freg);
|
||||
#else
|
||||
fpair = 1 ^ freg;
|
||||
avalue[i] = (UINT32 *) pfr + freg;
|
||||
#endif
|
||||
freg += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
avalue[i] = pgr + greg;
|
||||
#else
|
||||
avalue[i] = (UINT32 *) (pgr + greg) + 1;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
avalue[i] = pgr + greg;
|
||||
#else
|
||||
avalue[i] = (UINT32 *) (pgr + greg) + 1;
|
||||
#endif
|
||||
greg++;
|
||||
}
|
||||
else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
|
||||
{
|
||||
if (freg + 1 >= NFREGARG)
|
||||
avalue[i] = pgr + greg;
|
||||
else
|
||||
{
|
||||
avalue[i] = pfr + (freg >> 1);
|
||||
freg += 2;
|
||||
}
|
||||
greg++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64);
|
||||
|
||||
avalue[i] = pgr + greg;
|
||||
greg += n;
|
||||
}
|
||||
}
|
||||
|
||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
/* Tell ffi_closure_SYSV how to perform return type promotions. */
|
||||
return return_type (cif->rtype);
|
||||
}
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for SuperH - SHmedia.
|
||||
|
||||
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
|
||||
|
||||
/* ---- 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;
|
||||
|
||||
#define FFI_EXTRA_CIF_FIELDS long long flags2
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 32
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,539 +0,0 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 2003, 2004, 2006, 2008 Kaz Kojima
|
||||
|
||||
SuperH SHmedia 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
|
||||
/* 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
|
||||
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
#define OFS_FLT 0
|
||||
#else
|
||||
#define OFS_FLT 4
|
||||
#endif
|
||||
|
||||
.section .text..SHmedia32,"ax"
|
||||
|
||||
# r2: ffi_prep_args
|
||||
# r3: &ecif
|
||||
# r4: bytes
|
||||
# r5: flags
|
||||
# r6: flags2
|
||||
# r7: rvalue
|
||||
# r8: fn
|
||||
|
||||
# This assumes we are using gas.
|
||||
.align 5
|
||||
ENTRY(ffi_call_SYSV)
|
||||
# Save registers
|
||||
.LFB1:
|
||||
addi.l r15, -48, r15
|
||||
.LCFI0:
|
||||
st.q r15, 40, r32
|
||||
st.q r15, 32, r31
|
||||
st.q r15, 24, r30
|
||||
st.q r15, 16, r29
|
||||
st.q r15, 8, r28
|
||||
st.l r15, 4, r18
|
||||
st.l r15, 0, r14
|
||||
.LCFI1:
|
||||
add.l r15, r63, r14
|
||||
.LCFI2:
|
||||
# add r4, r63, r28
|
||||
add r5, r63, r29
|
||||
add r6, r63, r30
|
||||
add r7, r63, r31
|
||||
add r8, r63, r32
|
||||
|
||||
addi r4, (64 + 7), r4
|
||||
andi r4, ~7, r4
|
||||
sub.l r15, r4, r15
|
||||
|
||||
ptabs/l r2, tr0
|
||||
add r15, r63, r2
|
||||
blink tr0, r18
|
||||
|
||||
addi r15, 64, r22
|
||||
movi 0, r0
|
||||
movi 0, r1
|
||||
movi -1, r23
|
||||
|
||||
pt/l 1f, tr1
|
||||
bnei/l r29, FFI_TYPE_STRUCT, tr1
|
||||
ld.l r15, 0, r19
|
||||
addi r15, 8, r15
|
||||
addi r0, 1, r0
|
||||
1:
|
||||
|
||||
.L_pass:
|
||||
andi r30, 3, r20
|
||||
shlri r30, 2, r30
|
||||
|
||||
pt/l .L_call_it, tr0
|
||||
pt/l .L_pass_i, tr1
|
||||
pt/l .L_pass_f, tr2
|
||||
|
||||
beqi/l r20, FFI_TYPE_VOID, tr0
|
||||
beqi/l r20, FFI_TYPE_INT, tr1
|
||||
beqi/l r20, FFI_TYPE_FLOAT, tr2
|
||||
|
||||
.L_pass_d:
|
||||
addi r0, 1, r0
|
||||
pt/l 3f, tr0
|
||||
movi 12, r20
|
||||
bge/l r1, r20, tr0
|
||||
|
||||
pt/l .L_pop_d, tr1
|
||||
pt/l 2f, tr0
|
||||
blink tr1, r63
|
||||
2:
|
||||
addi.l r15, 8, r15
|
||||
3:
|
||||
pt/l .L_pass, tr0
|
||||
addi r1, 2, r1
|
||||
blink tr0, r63
|
||||
|
||||
.L_pop_d:
|
||||
pt/l .L_pop_d_tbl, tr1
|
||||
gettr tr1, r20
|
||||
shlli r1, 2, r21
|
||||
add r20, r21, r20
|
||||
ptabs/l r20, tr1
|
||||
blink tr1, r63
|
||||
|
||||
.L_pop_d_tbl:
|
||||
fld.d r15, 0, dr0
|
||||
blink tr0, r63
|
||||
fld.d r15, 0, dr2
|
||||
blink tr0, r63
|
||||
fld.d r15, 0, dr4
|
||||
blink tr0, r63
|
||||
fld.d r15, 0, dr6
|
||||
blink tr0, r63
|
||||
fld.d r15, 0, dr8
|
||||
blink tr0, r63
|
||||
fld.d r15, 0, dr10
|
||||
blink tr0, r63
|
||||
|
||||
.L_pass_f:
|
||||
addi r0, 1, r0
|
||||
pt/l 3f, tr0
|
||||
movi 12, r20
|
||||
bge/l r1, r20, tr0
|
||||
|
||||
pt/l .L_pop_f, tr1
|
||||
pt/l 2f, tr0
|
||||
blink tr1, r63
|
||||
2:
|
||||
addi.l r15, 8, r15
|
||||
3:
|
||||
pt/l .L_pass, tr0
|
||||
blink tr0, r63
|
||||
|
||||
.L_pop_f:
|
||||
pt/l .L_pop_f_tbl, tr1
|
||||
pt/l 5f, tr2
|
||||
gettr tr1, r20
|
||||
bge/l r23, r63, tr2
|
||||
add r1, r63, r23
|
||||
shlli r1, 3, r21
|
||||
addi r1, 2, r1
|
||||
add r20, r21, r20
|
||||
ptabs/l r20, tr1
|
||||
blink tr1, r63
|
||||
5:
|
||||
addi r23, 1, r21
|
||||
movi -1, r23
|
||||
shlli r21, 3, r21
|
||||
add r20, r21, r20
|
||||
ptabs/l r20, tr1
|
||||
blink tr1, r63
|
||||
|
||||
.L_pop_f_tbl:
|
||||
fld.s r15, OFS_FLT, fr0
|
||||
blink tr0, r63
|
||||
fld.s r15, OFS_FLT, fr1
|
||||
blink tr0, r63
|
||||
fld.s r15, OFS_FLT, fr2
|
||||
blink tr0, r63
|
||||
fld.s r15, OFS_FLT, fr3
|
||||
blink tr0, r63
|
||||
fld.s r15, OFS_FLT, fr4
|
||||
blink tr0, r63
|
||||
fld.s r15, OFS_FLT, fr5
|
||||
blink tr0, r63
|
||||
fld.s r15, OFS_FLT, fr6
|
||||
blink tr0, r63
|
||||
fld.s r15, OFS_FLT, fr7
|
||||
blink tr0, r63
|
||||
fld.s r15, OFS_FLT, fr8
|
||||
blink tr0, r63
|
||||
fld.s r15, OFS_FLT, fr9
|
||||
blink tr0, r63
|
||||
fld.s r15, OFS_FLT, fr10
|
||||
blink tr0, r63
|
||||
fld.s r15, OFS_FLT, fr11
|
||||
blink tr0, r63
|
||||
|
||||
.L_pass_i:
|
||||
pt/l 3f, tr0
|
||||
movi 8, r20
|
||||
bge/l r0, r20, tr0
|
||||
|
||||
pt/l .L_pop_i, tr1
|
||||
pt/l 2f, tr0
|
||||
blink tr1, r63
|
||||
2:
|
||||
addi.l r15, 8, r15
|
||||
3:
|
||||
pt/l .L_pass, tr0
|
||||
addi r0, 1, r0
|
||||
blink tr0, r63
|
||||
|
||||
.L_pop_i:
|
||||
pt/l .L_pop_i_tbl, tr1
|
||||
gettr tr1, r20
|
||||
shlli r0, 3, r21
|
||||
add r20, r21, r20
|
||||
ptabs/l r20, tr1
|
||||
blink tr1, r63
|
||||
|
||||
.L_pop_i_tbl:
|
||||
ld.q r15, 0, r2
|
||||
blink tr0, r63
|
||||
ld.q r15, 0, r3
|
||||
blink tr0, r63
|
||||
ld.q r15, 0, r4
|
||||
blink tr0, r63
|
||||
ld.q r15, 0, r5
|
||||
blink tr0, r63
|
||||
ld.q r15, 0, r6
|
||||
blink tr0, r63
|
||||
ld.q r15, 0, r7
|
||||
blink tr0, r63
|
||||
ld.q r15, 0, r8
|
||||
blink tr0, r63
|
||||
ld.q r15, 0, r9
|
||||
blink tr0, r63
|
||||
|
||||
.L_call_it:
|
||||
# call function
|
||||
pt/l 1f, tr1
|
||||
bnei/l r29, FFI_TYPE_STRUCT, tr1
|
||||
add r19, r63, r2
|
||||
1:
|
||||
add r22, r63, r15
|
||||
ptabs/l r32, tr0
|
||||
blink tr0, r18
|
||||
|
||||
pt/l .L_ret_i, tr0
|
||||
pt/l .L_ret_ll, tr1
|
||||
pt/l .L_ret_d, tr2
|
||||
pt/l .L_ret_f, tr3
|
||||
pt/l .L_epilogue, tr4
|
||||
|
||||
beqi/l r29, FFI_TYPE_INT, tr0
|
||||
beqi/l r29, FFI_TYPE_UINT32, tr0
|
||||
beqi/l r29, FFI_TYPE_SINT64, tr1
|
||||
beqi/l r29, FFI_TYPE_UINT64, tr1
|
||||
beqi/l r29, FFI_TYPE_DOUBLE, tr2
|
||||
beqi/l r29, FFI_TYPE_FLOAT, tr3
|
||||
|
||||
pt/l .L_ret_q, tr0
|
||||
pt/l .L_ret_h, tr1
|
||||
|
||||
beqi/l r29, FFI_TYPE_UINT8, tr0
|
||||
beqi/l r29, FFI_TYPE_UINT16, tr1
|
||||
blink tr4, r63
|
||||
|
||||
.L_ret_d:
|
||||
fst.d r31, 0, dr0
|
||||
blink tr4, r63
|
||||
|
||||
.L_ret_ll:
|
||||
st.q r31, 0, r2
|
||||
blink tr4, r63
|
||||
|
||||
.L_ret_f:
|
||||
fst.s r31, OFS_FLT, fr0
|
||||
blink tr4, r63
|
||||
|
||||
.L_ret_q:
|
||||
st.b r31, 0, r2
|
||||
blink tr4, r63
|
||||
|
||||
.L_ret_h:
|
||||
st.w r31, 0, r2
|
||||
blink tr4, r63
|
||||
|
||||
.L_ret_i:
|
||||
st.l r31, 0, r2
|
||||
# Fall
|
||||
|
||||
.L_epilogue:
|
||||
# Remove the space we pushed for the args
|
||||
add r14, r63, r15
|
||||
|
||||
ld.l r15, 0, r14
|
||||
ld.l r15, 4, r18
|
||||
ld.q r15, 8, r28
|
||||
ld.q r15, 16, r29
|
||||
ld.q r15, 24, r30
|
||||
ld.q r15, 32, r31
|
||||
ld.q r15, 40, r32
|
||||
addi.l r15, 48, r15
|
||||
ptabs r18, tr0
|
||||
blink tr0, r63
|
||||
|
||||
.LFE1:
|
||||
.ffi_call_SYSV_end:
|
||||
.size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
|
||||
|
||||
.align 5
|
||||
ENTRY(ffi_closure_SYSV)
|
||||
.LFB2:
|
||||
addi.l r15, -136, r15
|
||||
.LCFI3:
|
||||
st.l r15, 12, r18
|
||||
st.l r15, 8, r14
|
||||
st.l r15, 4, r12
|
||||
.LCFI4:
|
||||
add r15, r63, r14
|
||||
.LCFI5:
|
||||
/* Stack layout:
|
||||
...
|
||||
64 bytes (register parameters)
|
||||
48 bytes (floating register parameters)
|
||||
8 bytes (result)
|
||||
4 bytes (r18)
|
||||
4 bytes (r14)
|
||||
4 bytes (r12)
|
||||
4 bytes (for align)
|
||||
<- new stack pointer
|
||||
*/
|
||||
fst.d r14, 24, dr0
|
||||
fst.d r14, 32, dr2
|
||||
fst.d r14, 40, dr4
|
||||
fst.d r14, 48, dr6
|
||||
fst.d r14, 56, dr8
|
||||
fst.d r14, 64, dr10
|
||||
st.q r14, 72, r2
|
||||
st.q r14, 80, r3
|
||||
st.q r14, 88, r4
|
||||
st.q r14, 96, r5
|
||||
st.q r14, 104, r6
|
||||
st.q r14, 112, r7
|
||||
st.q r14, 120, r8
|
||||
st.q r14, 128, r9
|
||||
|
||||
add r1, r63, r2
|
||||
addi r14, 16, r3
|
||||
addi r14, 72, r4
|
||||
addi r14, 24, r5
|
||||
addi r14, 136, r6
|
||||
#ifdef PIC
|
||||
movi (((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) >> 16) & 65535), r12
|
||||
shori ((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) & 65535), r12
|
||||
.LPCS0: ptrel/u r12, tr0
|
||||
movi ((ffi_closure_helper_SYSV@GOTPLT) & 65535), r1
|
||||
gettr tr0, r12
|
||||
ldx.l r1, r12, r1
|
||||
ptabs r1, tr0
|
||||
#else
|
||||
pt/l ffi_closure_helper_SYSV, tr0
|
||||
#endif
|
||||
blink tr0, r18
|
||||
|
||||
shlli r2, 1, r1
|
||||
movi (((datalabel .L_table) >> 16) & 65535), r2
|
||||
shori ((datalabel .L_table) & 65535), r2
|
||||
ldx.w r2, r1, r1
|
||||
add r1, r2, r1
|
||||
pt/l .L_case_v, tr1
|
||||
ptabs r1, tr0
|
||||
blink tr0, r63
|
||||
|
||||
.align 2
|
||||
.L_table:
|
||||
.word .L_case_v - datalabel .L_table /* FFI_TYPE_VOID */
|
||||
.word .L_case_i - datalabel .L_table /* FFI_TYPE_INT */
|
||||
.word .L_case_f - datalabel .L_table /* FFI_TYPE_FLOAT */
|
||||
.word .L_case_d - datalabel .L_table /* FFI_TYPE_DOUBLE */
|
||||
.word .L_case_d - datalabel .L_table /* FFI_TYPE_LONGDOUBLE */
|
||||
.word .L_case_uq - datalabel .L_table /* FFI_TYPE_UINT8 */
|
||||
.word .L_case_q - datalabel .L_table /* FFI_TYPE_SINT8 */
|
||||
.word .L_case_uh - datalabel .L_table /* FFI_TYPE_UINT16 */
|
||||
.word .L_case_h - datalabel .L_table /* FFI_TYPE_SINT16 */
|
||||
.word .L_case_i - datalabel .L_table /* FFI_TYPE_UINT32 */
|
||||
.word .L_case_i - datalabel .L_table /* FFI_TYPE_SINT32 */
|
||||
.word .L_case_ll - datalabel .L_table /* FFI_TYPE_UINT64 */
|
||||
.word .L_case_ll - datalabel .L_table /* FFI_TYPE_SINT64 */
|
||||
.word .L_case_v - datalabel .L_table /* FFI_TYPE_STRUCT */
|
||||
.word .L_case_i - datalabel .L_table /* FFI_TYPE_POINTER */
|
||||
|
||||
.align 2
|
||||
.L_case_d:
|
||||
fld.d r14, 16, dr0
|
||||
blink tr1, r63
|
||||
.L_case_f:
|
||||
fld.s r14, 16, fr0
|
||||
blink tr1, r63
|
||||
.L_case_ll:
|
||||
ld.q r14, 16, r2
|
||||
blink tr1, r63
|
||||
.L_case_i:
|
||||
ld.l r14, 16, r2
|
||||
blink tr1, r63
|
||||
.L_case_q:
|
||||
ld.b r14, 16, r2
|
||||
blink tr1, r63
|
||||
.L_case_uq:
|
||||
ld.ub r14, 16, r2
|
||||
blink tr1, r63
|
||||
.L_case_h:
|
||||
ld.w r14, 16, r2
|
||||
blink tr1, r63
|
||||
.L_case_uh:
|
||||
ld.uw r14, 16, r2
|
||||
blink tr1, r63
|
||||
.L_case_v:
|
||||
add.l r14, r63, r15
|
||||
ld.l r15, 4, r12
|
||||
ld.l r15, 8, r14
|
||||
ld.l r15, 12, r18
|
||||
addi.l r15, 136, r15
|
||||
ptabs r18, tr0
|
||||
blink tr0, r63
|
||||
|
||||
.LFE2:
|
||||
.ffi_closure_SYSV_end:
|
||||
.size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
|
||||
.section ".eh_frame","aw",@progbits
|
||||
__FRAME_BEGIN__:
|
||||
.4byte .LECIE1-.LSCIE1 /* Length of Common Information Entry */
|
||||
.LSCIE1:
|
||||
.4byte 0x0 /* CIE Identifier Tag */
|
||||
.byte 0x1 /* CIE Version */
|
||||
#ifdef PIC
|
||||
.ascii "zR\0" /* CIE Augmentation */
|
||||
#else
|
||||
.byte 0x0 /* CIE Augmentation */
|
||||
#endif
|
||||
.uleb128 0x1 /* CIE Code Alignment Factor */
|
||||
.sleb128 -4 /* CIE Data Alignment Factor */
|
||||
.byte 0x12 /* CIE RA Column */
|
||||
#ifdef PIC
|
||||
.uleb128 0x1 /* Augmentation size */
|
||||
.byte 0x10 /* FDE Encoding (pcrel) */
|
||||
#endif
|
||||
.byte 0xc /* DW_CFA_def_cfa */
|
||||
.uleb128 0xf
|
||||
.uleb128 0x0
|
||||
.align 2
|
||||
.LECIE1:
|
||||
.LSFDE1:
|
||||
.4byte datalabel .LEFDE1-datalabel .LASFDE1 /* FDE Length */
|
||||
.LASFDE1:
|
||||
.4byte datalabel .LASFDE1-datalabel __FRAME_BEGIN__
|
||||
#ifdef PIC
|
||||
.4byte .LFB1-. /* FDE initial location */
|
||||
#else
|
||||
.4byte .LFB1 /* FDE initial location */
|
||||
#endif
|
||||
.4byte datalabel .LFE1-datalabel .LFB1 /* FDE address range */
|
||||
#ifdef PIC
|
||||
.uleb128 0x0 /* Augmentation size */
|
||||
#endif
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte datalabel .LCFI0-datalabel .LFB1
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset */
|
||||
.uleb128 0x30
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte datalabel .LCFI1-datalabel .LCFI0
|
||||
.byte 0x8e /* DW_CFA_offset, column 0xe */
|
||||
.uleb128 0xc
|
||||
.byte 0x92 /* DW_CFA_offset, column 0x12 */
|
||||
.uleb128 0xb
|
||||
.byte 0x9c /* DW_CFA_offset, column 0x1c */
|
||||
.uleb128 0xa
|
||||
.byte 0x9d /* DW_CFA_offset, column 0x1d */
|
||||
.uleb128 0x8
|
||||
.byte 0x9e /* DW_CFA_offset, column 0x1e */
|
||||
.uleb128 0x6
|
||||
.byte 0x9f /* DW_CFA_offset, column 0x1f */
|
||||
.uleb128 0x4
|
||||
.byte 0xa0 /* DW_CFA_offset, column 0x20 */
|
||||
.uleb128 0x2
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte datalabel .LCFI2-datalabel .LCFI1
|
||||
.byte 0xd /* DW_CFA_def_cfa_register */
|
||||
.uleb128 0xe
|
||||
.align 2
|
||||
.LEFDE1:
|
||||
|
||||
.LSFDE3:
|
||||
.4byte datalabel .LEFDE3-datalabel .LASFDE3 /* FDE Length */
|
||||
.LASFDE3:
|
||||
.4byte datalabel .LASFDE3-datalabel __FRAME_BEGIN__
|
||||
#ifdef PIC
|
||||
.4byte .LFB2-. /* FDE initial location */
|
||||
#else
|
||||
.4byte .LFB2 /* FDE initial location */
|
||||
#endif
|
||||
.4byte datalabel .LFE2-datalabel .LFB2 /* FDE address range */
|
||||
#ifdef PIC
|
||||
.uleb128 0x0 /* Augmentation size */
|
||||
#endif
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte datalabel .LCFI3-datalabel .LFB2
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset */
|
||||
.uleb128 0x88
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte datalabel .LCFI4-datalabel .LCFI3
|
||||
.byte 0x8c /* DW_CFA_offset, column 0xc */
|
||||
.uleb128 0x21
|
||||
.byte 0x8e /* DW_CFA_offset, column 0xe */
|
||||
.uleb128 0x20
|
||||
.byte 0x92 /* DW_CFA_offset, column 0x12 */
|
||||
.uleb128 0x1f
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte datalabel .LCFI5-datalabel .LCFI4
|
||||
.byte 0xd /* DW_CFA_def_cfa_register */
|
||||
.uleb128 0xe
|
||||
.align 2
|
||||
.LEFDE3:
|
||||
Reference in New Issue
Block a user