mirror of
https://github.com/beefytech/Beef.git
synced 2025-07-04 15:26:00 +02:00
Initial checkin
This commit is contained in:
parent
c74712dad9
commit
078564ac9e
3242 changed files with 1616395 additions and 0 deletions
355
BeefySysLib/third_party/libffi/src/tile/ffi.c
vendored
Normal file
355
BeefySysLib/third_party/libffi/src/tile/ffi.c
vendored
Normal file
|
@ -0,0 +1,355 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2012 Tilera Corp.
|
||||
|
||||
TILE 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 <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <arch/abi.h>
|
||||
#include <arch/icache.h>
|
||||
#include <arch/opcode.h>
|
||||
|
||||
|
||||
/* The first 10 registers are used to pass arguments and return values. */
|
||||
#define NUM_ARG_REGS 10
|
||||
|
||||
/* Performs a raw function call with the given NUM_ARG_REGS register arguments
|
||||
and the specified additional stack arguments (if any). */
|
||||
extern void ffi_call_tile(ffi_sarg reg_args[NUM_ARG_REGS],
|
||||
const ffi_sarg *stack_args,
|
||||
size_t stack_args_bytes,
|
||||
void (*fnaddr)(void))
|
||||
FFI_HIDDEN;
|
||||
|
||||
/* This handles the raw call from the closure stub, cleaning up the
|
||||
parameters and delegating to ffi_closure_tile_inner. */
|
||||
extern void ffi_closure_tile(void) FFI_HIDDEN;
|
||||
|
||||
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
/* We always allocate room for all registers. Even if we don't
|
||||
use them as parameters, they get returned in the same array
|
||||
as struct return values so we need to make room. */
|
||||
if (cif->bytes < NUM_ARG_REGS * FFI_SIZEOF_ARG)
|
||||
cif->bytes = NUM_ARG_REGS * FFI_SIZEOF_ARG;
|
||||
|
||||
if (cif->rtype->size > NUM_ARG_REGS * FFI_SIZEOF_ARG)
|
||||
cif->flags = FFI_TYPE_STRUCT;
|
||||
else
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
|
||||
/* Nothing to do. */
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
|
||||
static long
|
||||
assign_to_ffi_arg(ffi_sarg *out, void *in, const ffi_type *type,
|
||||
int write_to_reg)
|
||||
{
|
||||
switch (type->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*out = *(SINT8 *)in;
|
||||
return 1;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*out = *(UINT8 *)in;
|
||||
return 1;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*out = *(SINT16 *)in;
|
||||
return 1;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*out = *(UINT16 *)in;
|
||||
return 1;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
#ifndef __LP64__
|
||||
case FFI_TYPE_POINTER:
|
||||
#endif
|
||||
/* Note that even unsigned 32-bit quantities are sign extended
|
||||
on tilegx when stored in a register. */
|
||||
*out = *(SINT32 *)in;
|
||||
return 1;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
#ifdef __tilegx__
|
||||
if (write_to_reg)
|
||||
{
|
||||
/* Properly sign extend the value. */
|
||||
union { float f; SINT32 s32; } val;
|
||||
val.f = *(float *)in;
|
||||
*out = val.s32;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
*(float *)out = *(float *)in;
|
||||
}
|
||||
return 1;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
#ifdef __LP64__
|
||||
case FFI_TYPE_POINTER:
|
||||
#endif
|
||||
*(UINT64 *)out = *(UINT64 *)in;
|
||||
return sizeof(UINT64) / FFI_SIZEOF_ARG;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
memcpy(out, in, type->size);
|
||||
return (type->size + FFI_SIZEOF_ARG - 1) / FFI_SIZEOF_ARG;
|
||||
|
||||
case FFI_TYPE_VOID:
|
||||
/* Must be a return type. Nothing to do. */
|
||||
return 0;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
ffi_sarg * const arg_mem = alloca(cif->bytes);
|
||||
ffi_sarg * const reg_args = arg_mem;
|
||||
ffi_sarg * const stack_args = ®_args[NUM_ARG_REGS];
|
||||
ffi_sarg *argp = arg_mem;
|
||||
ffi_type ** const arg_types = cif->arg_types;
|
||||
const long num_args = cif->nargs;
|
||||
long i;
|
||||
|
||||
if (cif->flags == FFI_TYPE_STRUCT)
|
||||
{
|
||||
/* Pass a hidden pointer to the return value. We make sure there
|
||||
is scratch space for the callee to store the return value even if
|
||||
our caller doesn't care about it. */
|
||||
*argp++ = (intptr_t)(rvalue ? rvalue : alloca(cif->rtype->size));
|
||||
|
||||
/* No more work needed to return anything. */
|
||||
rvalue = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_args; i++)
|
||||
{
|
||||
ffi_type *type = arg_types[i];
|
||||
void * const arg_in = avalue[i];
|
||||
ptrdiff_t arg_word = argp - arg_mem;
|
||||
|
||||
#ifndef __tilegx__
|
||||
/* Doubleword-aligned values are always in an even-number register
|
||||
pair, or doubleword-aligned stack slot if out of registers. */
|
||||
long align = arg_word & (type->alignment > FFI_SIZEOF_ARG);
|
||||
argp += align;
|
||||
arg_word += align;
|
||||
#endif
|
||||
|
||||
if (type->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
const size_t arg_size_in_words =
|
||||
(type->size + FFI_SIZEOF_ARG - 1) / FFI_SIZEOF_ARG;
|
||||
|
||||
if (arg_word < NUM_ARG_REGS &&
|
||||
arg_word + arg_size_in_words > NUM_ARG_REGS)
|
||||
{
|
||||
/* Args are not allowed to span registers and the stack. */
|
||||
argp = stack_args;
|
||||
}
|
||||
|
||||
memcpy(argp, arg_in, type->size);
|
||||
argp += arg_size_in_words;
|
||||
}
|
||||
else
|
||||
{
|
||||
argp += assign_to_ffi_arg(argp, arg_in, arg_types[i], 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Actually do the call. */
|
||||
ffi_call_tile(reg_args, stack_args,
|
||||
cif->bytes - (NUM_ARG_REGS * FFI_SIZEOF_ARG), fn);
|
||||
|
||||
if (rvalue != NULL)
|
||||
assign_to_ffi_arg(rvalue, reg_args, cif->rtype, 0);
|
||||
}
|
||||
|
||||
|
||||
/* Template code for closure. */
|
||||
extern const UINT64 ffi_template_tramp_tile[] FFI_HIDDEN;
|
||||
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure *closure,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
#ifdef __tilegx__
|
||||
/* TILE-Gx */
|
||||
SINT64 c;
|
||||
SINT64 h;
|
||||
int s;
|
||||
UINT64 *out;
|
||||
|
||||
if (cif->abi != FFI_UNIX)
|
||||
return FFI_BAD_ABI;
|
||||
|
||||
out = (UINT64 *)closure->tramp;
|
||||
|
||||
c = (intptr_t)closure;
|
||||
h = (intptr_t)ffi_closure_tile;
|
||||
s = 0;
|
||||
|
||||
/* Find the smallest shift count that doesn't lose information
|
||||
(i.e. no need to explicitly insert high bits of the address that
|
||||
are just the sign extension of the low bits). */
|
||||
while ((c >> s) != (SINT16)(c >> s) || (h >> s) != (SINT16)(h >> s))
|
||||
s += 16;
|
||||
|
||||
#define OPS(a, b, shift) \
|
||||
(create_Imm16_X0((a) >> (shift)) | create_Imm16_X1((b) >> (shift)))
|
||||
|
||||
/* Emit the moveli. */
|
||||
*out++ = ffi_template_tramp_tile[0] | OPS(c, h, s);
|
||||
for (s -= 16; s >= 0; s -= 16)
|
||||
*out++ = ffi_template_tramp_tile[1] | OPS(c, h, s);
|
||||
|
||||
#undef OPS
|
||||
|
||||
*out++ = ffi_template_tramp_tile[2];
|
||||
|
||||
#else
|
||||
/* TILEPro */
|
||||
UINT64 *out;
|
||||
intptr_t delta;
|
||||
|
||||
if (cif->abi != FFI_UNIX)
|
||||
return FFI_BAD_ABI;
|
||||
|
||||
out = (UINT64 *)closure->tramp;
|
||||
delta = (intptr_t)ffi_closure_tile - (intptr_t)codeloc;
|
||||
|
||||
*out++ = ffi_template_tramp_tile[0] | create_JOffLong_X1(delta >> 3);
|
||||
#endif
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
invalidate_icache(closure->tramp, (char *)out - closure->tramp,
|
||||
getpagesize());
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
|
||||
/* This is called by the assembly wrapper for closures. This does
|
||||
all of the work. On entry reg_args[0] holds the values the registers
|
||||
had when the closure was invoked. On return reg_args[1] holds the register
|
||||
values to be returned to the caller (many of which may be garbage). */
|
||||
void FFI_HIDDEN
|
||||
ffi_closure_tile_inner(ffi_closure *closure,
|
||||
ffi_sarg reg_args[2][NUM_ARG_REGS],
|
||||
ffi_sarg *stack_args)
|
||||
{
|
||||
ffi_cif * const cif = closure->cif;
|
||||
void ** const avalue = alloca(cif->nargs * sizeof(void *));
|
||||
void *rvalue;
|
||||
ffi_type ** const arg_types = cif->arg_types;
|
||||
ffi_sarg * const reg_args_in = reg_args[0];
|
||||
ffi_sarg * const reg_args_out = reg_args[1];
|
||||
ffi_sarg * argp;
|
||||
long i, arg_word, nargs = cif->nargs;
|
||||
/* Use a union to guarantee proper alignment for double. */
|
||||
union { ffi_sarg arg[NUM_ARG_REGS]; double d; UINT64 u64; } closure_ret;
|
||||
|
||||
/* Start out reading register arguments. */
|
||||
argp = reg_args_in;
|
||||
|
||||
/* Copy the caller's structure return address to that the closure
|
||||
returns the data directly to the caller. */
|
||||
if (cif->flags == FFI_TYPE_STRUCT)
|
||||
{
|
||||
/* Return by reference via hidden pointer. */
|
||||
rvalue = (void *)(intptr_t)*argp++;
|
||||
arg_word = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Return the value in registers. */
|
||||
rvalue = &closure_ret;
|
||||
arg_word = 0;
|
||||
}
|
||||
|
||||
/* Grab the addresses of the arguments. */
|
||||
for (i = 0; i < nargs; i++)
|
||||
{
|
||||
ffi_type * const type = arg_types[i];
|
||||
const size_t arg_size_in_words =
|
||||
(type->size + FFI_SIZEOF_ARG - 1) / FFI_SIZEOF_ARG;
|
||||
|
||||
#ifndef __tilegx__
|
||||
/* Doubleword-aligned values are always in an even-number register
|
||||
pair, or doubleword-aligned stack slot if out of registers. */
|
||||
long align = arg_word & (type->alignment > FFI_SIZEOF_ARG);
|
||||
argp += align;
|
||||
arg_word += align;
|
||||
#endif
|
||||
|
||||
if (arg_word == NUM_ARG_REGS ||
|
||||
(arg_word < NUM_ARG_REGS &&
|
||||
arg_word + arg_size_in_words > NUM_ARG_REGS))
|
||||
{
|
||||
/* Switch to reading arguments from the stack. */
|
||||
argp = stack_args;
|
||||
arg_word = NUM_ARG_REGS;
|
||||
}
|
||||
|
||||
avalue[i] = argp;
|
||||
argp += arg_size_in_words;
|
||||
arg_word += arg_size_in_words;
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
closure->fun(cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
if (cif->flags != FFI_TYPE_STRUCT)
|
||||
{
|
||||
/* Canonicalize for register representation. */
|
||||
assign_to_ffi_arg(reg_args_out, &closure_ret, cif->rtype, 1);
|
||||
}
|
||||
}
|
65
BeefySysLib/third_party/libffi/src/tile/ffitarget.h
vendored
Normal file
65
BeefySysLib/third_party/libffi/src/tile/ffitarget.h
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 2012 Tilera Corp.
|
||||
Target configuration macros for TILE.
|
||||
|
||||
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_H
|
||||
#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead."
|
||||
#endif
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
|
||||
#include <arch/abi.h>
|
||||
|
||||
typedef uint_reg_t ffi_arg;
|
||||
typedef int_reg_t ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_UNIX,
|
||||
FFI_LAST_ABI,
|
||||
FFI_DEFAULT_ABI = FFI_UNIX
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
#define FFI_CLOSURES 1
|
||||
|
||||
#ifdef __tilegx__
|
||||
/* We always pass 8-byte values, even in -m32 mode. */
|
||||
# define FFI_SIZEOF_ARG 8
|
||||
# ifdef __LP64__
|
||||
# define FFI_TRAMPOLINE_SIZE (8 * 5) /* 5 bundles */
|
||||
# else
|
||||
# define FFI_TRAMPOLINE_SIZE (8 * 3) /* 3 bundles */
|
||||
# endif
|
||||
#else
|
||||
# define FFI_SIZEOF_ARG 4
|
||||
# define FFI_TRAMPOLINE_SIZE 8 /* 1 bundle */
|
||||
#endif
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
360
BeefySysLib/third_party/libffi/src/tile/tile.S
vendored
Normal file
360
BeefySysLib/third_party/libffi/src/tile/tile.S
vendored
Normal file
|
@ -0,0 +1,360 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
tile.S - Copyright (c) 2011 Tilera Corp.
|
||||
|
||||
Tilera TILEPro and TILE-Gx 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>
|
||||
|
||||
/* Number of bytes in a register. */
|
||||
#define REG_SIZE FFI_SIZEOF_ARG
|
||||
|
||||
/* Number of bytes in stack linkage area for backtracing.
|
||||
|
||||
A note about the ABI: on entry to a procedure, sp points to a stack
|
||||
slot where it must spill the return address if it's not a leaf.
|
||||
REG_SIZE bytes beyond that is a slot owned by the caller which
|
||||
contains the sp value that the caller had when it was originally
|
||||
entered (i.e. the caller's frame pointer). */
|
||||
#define LINKAGE_SIZE (2 * REG_SIZE)
|
||||
|
||||
/* The first 10 registers are used to pass arguments and return values. */
|
||||
#define NUM_ARG_REGS 10
|
||||
|
||||
#ifdef __tilegx__
|
||||
#define SW st
|
||||
#define LW ld
|
||||
#define BGZT bgtzt
|
||||
#else
|
||||
#define SW sw
|
||||
#define LW lw
|
||||
#define BGZT bgzt
|
||||
#endif
|
||||
|
||||
|
||||
/* void ffi_call_tile (int_reg_t reg_args[NUM_ARG_REGS],
|
||||
const int_reg_t *stack_args,
|
||||
unsigned long stack_args_bytes,
|
||||
void (*fnaddr)(void));
|
||||
|
||||
On entry, REG_ARGS contain the outgoing register values,
|
||||
and STACK_ARGS containts STACK_ARG_BYTES of additional values
|
||||
to be passed on the stack. If STACK_ARG_BYTES is zero, then
|
||||
STACK_ARGS is ignored.
|
||||
|
||||
When the invoked function returns, the values of r0-r9 are
|
||||
blindly stored back into REG_ARGS for the caller to examine. */
|
||||
|
||||
.section .text.ffi_call_tile, "ax", @progbits
|
||||
.align 8
|
||||
.globl ffi_call_tile
|
||||
FFI_HIDDEN(ffi_call_tile)
|
||||
ffi_call_tile:
|
||||
|
||||
/* Incoming arguments. */
|
||||
#define REG_ARGS r0
|
||||
#define INCOMING_STACK_ARGS r1
|
||||
#define STACK_ARG_BYTES r2
|
||||
#define ORIG_FNADDR r3
|
||||
|
||||
/* Temporary values. */
|
||||
#define FRAME_SIZE r10
|
||||
#define TMP r11
|
||||
#define TMP2 r12
|
||||
#define OUTGOING_STACK_ARGS r13
|
||||
#define REG_ADDR_PTR r14
|
||||
#define RETURN_REG_ADDR r15
|
||||
#define FNADDR r16
|
||||
|
||||
.cfi_startproc
|
||||
{
|
||||
/* Save return address. */
|
||||
SW sp, lr
|
||||
.cfi_offset lr, 0
|
||||
/* Prepare to spill incoming r52. */
|
||||
addi TMP, sp, -REG_SIZE
|
||||
/* Increase frame size to have room to spill r52 and REG_ARGS.
|
||||
The +7 is to round up mod 8. */
|
||||
addi FRAME_SIZE, STACK_ARG_BYTES, \
|
||||
REG_SIZE + REG_SIZE + LINKAGE_SIZE + 7
|
||||
}
|
||||
{
|
||||
/* Round stack frame size to a multiple of 8 to satisfy ABI. */
|
||||
andi FRAME_SIZE, FRAME_SIZE, -8
|
||||
/* Compute where to spill REG_ARGS value. */
|
||||
addi TMP2, sp, -(REG_SIZE * 2)
|
||||
}
|
||||
{
|
||||
/* Spill incoming r52. */
|
||||
SW TMP, r52
|
||||
.cfi_offset r52, -REG_SIZE
|
||||
/* Set up our frame pointer. */
|
||||
move r52, sp
|
||||
.cfi_def_cfa_register r52
|
||||
/* Push stack frame. */
|
||||
sub sp, sp, FRAME_SIZE
|
||||
}
|
||||
{
|
||||
/* Prepare to set up stack linkage. */
|
||||
addi TMP, sp, REG_SIZE
|
||||
/* Prepare to memcpy stack args. */
|
||||
addi OUTGOING_STACK_ARGS, sp, LINKAGE_SIZE
|
||||
/* Save REG_ARGS which we will need after we call the subroutine. */
|
||||
SW TMP2, REG_ARGS
|
||||
}
|
||||
{
|
||||
/* Set up linkage info to hold incoming stack pointer. */
|
||||
SW TMP, r52
|
||||
}
|
||||
{
|
||||
/* Skip stack args memcpy if we don't have any stack args (common). */
|
||||
blezt STACK_ARG_BYTES, .Ldone_stack_args_memcpy
|
||||
}
|
||||
|
||||
.Lmemcpy_stack_args:
|
||||
{
|
||||
/* Load incoming argument from stack_args. */
|
||||
LW TMP, INCOMING_STACK_ARGS
|
||||
addi INCOMING_STACK_ARGS, INCOMING_STACK_ARGS, REG_SIZE
|
||||
}
|
||||
{
|
||||
/* Store stack argument into outgoing stack argument area. */
|
||||
SW OUTGOING_STACK_ARGS, TMP
|
||||
addi OUTGOING_STACK_ARGS, OUTGOING_STACK_ARGS, REG_SIZE
|
||||
addi STACK_ARG_BYTES, STACK_ARG_BYTES, -REG_SIZE
|
||||
}
|
||||
{
|
||||
BGZT STACK_ARG_BYTES, .Lmemcpy_stack_args
|
||||
}
|
||||
.Ldone_stack_args_memcpy:
|
||||
|
||||
{
|
||||
/* Copy aside ORIG_FNADDR so we can overwrite its register. */
|
||||
move FNADDR, ORIG_FNADDR
|
||||
/* Prepare to load argument registers. */
|
||||
addi REG_ADDR_PTR, r0, REG_SIZE
|
||||
/* Load outgoing r0. */
|
||||
LW r0, r0
|
||||
}
|
||||
|
||||
/* Load up argument registers from the REG_ARGS array. */
|
||||
#define LOAD_REG(REG, PTR) \
|
||||
{ \
|
||||
LW REG, PTR ; \
|
||||
addi PTR, PTR, REG_SIZE \
|
||||
}
|
||||
|
||||
LOAD_REG(r1, REG_ADDR_PTR)
|
||||
LOAD_REG(r2, REG_ADDR_PTR)
|
||||
LOAD_REG(r3, REG_ADDR_PTR)
|
||||
LOAD_REG(r4, REG_ADDR_PTR)
|
||||
LOAD_REG(r5, REG_ADDR_PTR)
|
||||
LOAD_REG(r6, REG_ADDR_PTR)
|
||||
LOAD_REG(r7, REG_ADDR_PTR)
|
||||
LOAD_REG(r8, REG_ADDR_PTR)
|
||||
LOAD_REG(r9, REG_ADDR_PTR)
|
||||
|
||||
{
|
||||
/* Call the subroutine. */
|
||||
jalr FNADDR
|
||||
}
|
||||
|
||||
{
|
||||
/* Restore original lr. */
|
||||
LW lr, r52
|
||||
/* Prepare to recover ARGS, which we spilled earlier. */
|
||||
addi TMP, r52, -(2 * REG_SIZE)
|
||||
}
|
||||
{
|
||||
/* Restore ARGS, so we can fill it in with the return regs r0-r9. */
|
||||
LW RETURN_REG_ADDR, TMP
|
||||
/* Prepare to restore original r52. */
|
||||
addi TMP, r52, -REG_SIZE
|
||||
}
|
||||
|
||||
{
|
||||
/* Pop stack frame. */
|
||||
move sp, r52
|
||||
/* Restore original r52. */
|
||||
LW r52, TMP
|
||||
}
|
||||
|
||||
#define STORE_REG(REG, PTR) \
|
||||
{ \
|
||||
SW PTR, REG ; \
|
||||
addi PTR, PTR, REG_SIZE \
|
||||
}
|
||||
|
||||
/* Return all register values by reference. */
|
||||
STORE_REG(r0, RETURN_REG_ADDR)
|
||||
STORE_REG(r1, RETURN_REG_ADDR)
|
||||
STORE_REG(r2, RETURN_REG_ADDR)
|
||||
STORE_REG(r3, RETURN_REG_ADDR)
|
||||
STORE_REG(r4, RETURN_REG_ADDR)
|
||||
STORE_REG(r5, RETURN_REG_ADDR)
|
||||
STORE_REG(r6, RETURN_REG_ADDR)
|
||||
STORE_REG(r7, RETURN_REG_ADDR)
|
||||
STORE_REG(r8, RETURN_REG_ADDR)
|
||||
STORE_REG(r9, RETURN_REG_ADDR)
|
||||
|
||||
{
|
||||
jrp lr
|
||||
}
|
||||
|
||||
.cfi_endproc
|
||||
.size ffi_call_tile, .-ffi_call_tile
|
||||
|
||||
/* ffi_closure_tile(...)
|
||||
|
||||
On entry, lr points to the closure plus 8 bytes, and r10
|
||||
contains the actual return address.
|
||||
|
||||
This function simply dumps all register parameters into a stack array
|
||||
and passes the closure, the registers array, and the stack arguments
|
||||
to C code that does all of the actual closure processing. */
|
||||
|
||||
.section .text.ffi_closure_tile, "ax", @progbits
|
||||
.align 8
|
||||
.globl ffi_closure_tile
|
||||
FFI_HIDDEN(ffi_closure_tile)
|
||||
|
||||
.cfi_startproc
|
||||
/* Room to spill all NUM_ARG_REGS incoming registers, plus frame linkage. */
|
||||
#define CLOSURE_FRAME_SIZE (((NUM_ARG_REGS * REG_SIZE * 2 + LINKAGE_SIZE) + 7) & -8)
|
||||
ffi_closure_tile:
|
||||
{
|
||||
#ifdef __tilegx__
|
||||
st sp, lr
|
||||
.cfi_offset lr, 0
|
||||
#else
|
||||
/* Save return address (in r10 due to closure stub wrapper). */
|
||||
SW sp, r10
|
||||
.cfi_return_column r10
|
||||
.cfi_offset r10, 0
|
||||
#endif
|
||||
/* Compute address for stack frame linkage. */
|
||||
addli r10, sp, -(CLOSURE_FRAME_SIZE - REG_SIZE)
|
||||
}
|
||||
{
|
||||
/* Save incoming stack pointer in linkage area. */
|
||||
SW r10, sp
|
||||
.cfi_offset sp, -(CLOSURE_FRAME_SIZE - REG_SIZE)
|
||||
/* Push a new stack frame. */
|
||||
addli sp, sp, -CLOSURE_FRAME_SIZE
|
||||
.cfi_adjust_cfa_offset CLOSURE_FRAME_SIZE
|
||||
}
|
||||
|
||||
{
|
||||
/* Create pointer to where to start spilling registers. */
|
||||
addi r10, sp, LINKAGE_SIZE
|
||||
}
|
||||
|
||||
/* Spill all the incoming registers. */
|
||||
STORE_REG(r0, r10)
|
||||
STORE_REG(r1, r10)
|
||||
STORE_REG(r2, r10)
|
||||
STORE_REG(r3, r10)
|
||||
STORE_REG(r4, r10)
|
||||
STORE_REG(r5, r10)
|
||||
STORE_REG(r6, r10)
|
||||
STORE_REG(r7, r10)
|
||||
STORE_REG(r8, r10)
|
||||
{
|
||||
/* Save r9. */
|
||||
SW r10, r9
|
||||
#ifdef __tilegx__
|
||||
/* Pointer to closure is passed in r11. */
|
||||
move r0, r11
|
||||
#else
|
||||
/* Compute pointer to the closure object. Because the closure
|
||||
starts with a "jal ffi_closure_tile", we can just take the
|
||||
value of lr (a phony return address pointing into the closure)
|
||||
and subtract 8. */
|
||||
addi r0, lr, -8
|
||||
#endif
|
||||
/* Compute a pointer to the register arguments we just spilled. */
|
||||
addi r1, sp, LINKAGE_SIZE
|
||||
}
|
||||
{
|
||||
/* Compute a pointer to the extra stack arguments (if any). */
|
||||
addli r2, sp, CLOSURE_FRAME_SIZE + LINKAGE_SIZE
|
||||
/* Call C code to deal with all of the grotty details. */
|
||||
jal ffi_closure_tile_inner
|
||||
}
|
||||
{
|
||||
addli r10, sp, CLOSURE_FRAME_SIZE
|
||||
}
|
||||
{
|
||||
/* Restore the return address. */
|
||||
LW lr, r10
|
||||
/* Compute pointer to registers array. */
|
||||
addli r10, sp, LINKAGE_SIZE + (NUM_ARG_REGS * REG_SIZE)
|
||||
}
|
||||
/* Return all the register values, which C code may have set. */
|
||||
LOAD_REG(r0, r10)
|
||||
LOAD_REG(r1, r10)
|
||||
LOAD_REG(r2, r10)
|
||||
LOAD_REG(r3, r10)
|
||||
LOAD_REG(r4, r10)
|
||||
LOAD_REG(r5, r10)
|
||||
LOAD_REG(r6, r10)
|
||||
LOAD_REG(r7, r10)
|
||||
LOAD_REG(r8, r10)
|
||||
LOAD_REG(r9, r10)
|
||||
{
|
||||
/* Pop the frame. */
|
||||
addli sp, sp, CLOSURE_FRAME_SIZE
|
||||
jrp lr
|
||||
}
|
||||
|
||||
.cfi_endproc
|
||||
.size ffi_closure_tile, . - ffi_closure_tile
|
||||
|
||||
|
||||
/* What follows are code template instructions that get copied to the
|
||||
closure trampoline by ffi_prep_closure_loc. The zeroed operands
|
||||
get replaced by their proper values at runtime. */
|
||||
|
||||
.section .text.ffi_template_tramp_tile, "ax", @progbits
|
||||
.align 8
|
||||
.globl ffi_template_tramp_tile
|
||||
FFI_HIDDEN(ffi_template_tramp_tile)
|
||||
ffi_template_tramp_tile:
|
||||
#ifdef __tilegx__
|
||||
{
|
||||
moveli r11, 0 /* backpatched to address of containing closure. */
|
||||
moveli r10, 0 /* backpatched to ffi_closure_tile. */
|
||||
}
|
||||
/* Note: the following bundle gets generated multiple times
|
||||
depending on the pointer value (esp. useful for -m32 mode). */
|
||||
{ shl16insli r11, r11, 0 ; shl16insli r10, r10, 0 }
|
||||
{ info 2+8 /* for backtracer: -> pc in lr, frame size 0 */ ; jr r10 }
|
||||
#else
|
||||
/* 'jal .' yields a PC-relative offset of zero so we can OR in the
|
||||
right offset at runtime. */
|
||||
{ move r10, lr ; jal . /* ffi_closure_tile */ }
|
||||
#endif
|
||||
|
||||
.size ffi_template_tramp_tile, . - ffi_template_tramp_tile
|
Loading…
Add table
Add a link
Reference in a new issue