|
@@ -0,0 +1,878 @@
|
|
|
+From 38e46503a1f78166e5f0730133f15bb3cb70f588 Mon Sep 17 00:00:00 2001
|
|
|
+From: tianshuliang <tian_shuliang@hoperun.com>
|
|
|
+Date: Sun, 25 Apr 2021 13:51:41 +0800
|
|
|
+Subject: [PATCH] append support for csky
|
|
|
+
|
|
|
+---
|
|
|
+ configure.host | 5 +
|
|
|
+ src/csky/ffi.c | 395 +++++++++++++++++++++++++++++++++++++++++++
|
|
|
+ src/csky/ffitarget.h | 63 +++++++
|
|
|
+ src/csky/sysv.S | 371 ++++++++++++++++++++++++++++++++++++++++
|
|
|
+ 4 files changed, 834 insertions(+)
|
|
|
+ create mode 100644 src/csky/ffi.c
|
|
|
+ create mode 100644 src/csky/ffitarget.h
|
|
|
+ create mode 100644 src/csky/sysv.S
|
|
|
+
|
|
|
+diff --git a/configure.host b/configure.host
|
|
|
+index 9a72cda..3deed6c 100644
|
|
|
+--- a/configure.host
|
|
|
++++ b/configure.host
|
|
|
+@@ -214,6 +214,11 @@ case "${host}" in
|
|
|
+ TARGET=RISCV; TARGETDIR=riscv
|
|
|
+ SOURCES="ffi.c sysv.S"
|
|
|
+ ;;
|
|
|
++
|
|
|
++ csky*-*)
|
|
|
++ TARGET=CSKY; TARGETDIR=csky
|
|
|
++ SOURCES="ffi.c sysv.S"
|
|
|
++ ;;
|
|
|
+
|
|
|
+ s390-*-* | s390x-*-*)
|
|
|
+ TARGET=S390; TARGETDIR=s390
|
|
|
+diff --git a/src/csky/ffi.c b/src/csky/ffi.c
|
|
|
+new file mode 100644
|
|
|
+index 0000000..eb53848
|
|
|
+--- /dev/null
|
|
|
++++ b/src/csky/ffi.c
|
|
|
+@@ -0,0 +1,395 @@
|
|
|
++/* -----------------------------------------------------------------------
|
|
|
++ ffi.c
|
|
|
++
|
|
|
++ CSKY 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;
|
|
|
++ size_t alignment;
|
|
|
++
|
|
|
++ /* Align if necessary */
|
|
|
++ alignment = (*p_arg)->alignment;
|
|
|
++#ifdef __CSKYABIV1__
|
|
|
++ /*
|
|
|
++ * Adapt ABIV1 bug.
|
|
|
++ * If struct's size is larger than 8 bytes, then it always alignment as 4 bytes.
|
|
|
++ */
|
|
|
++ if (((*p_arg)->type == FFI_TYPE_STRUCT) && ((*p_arg)->size > 8) && (alignment == 8)) {
|
|
|
++ alignment = 4;
|
|
|
++ }
|
|
|
++#endif
|
|
|
++
|
|
|
++ if ((alignment - 1) & (unsigned) argp) {
|
|
|
++ argp = (char *) FFI_ALIGN(argp, alignment);
|
|
|
++ }
|
|
|
++
|
|
|
++ if ((*p_arg)->type == FFI_TYPE_STRUCT)
|
|
|
++ argp = (char *) FFI_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:
|
|
|
++#ifdef __CSKYBE__
|
|
|
++ memcpy((argp + 4 - (*p_arg)->size), *p_argv, (*p_arg)->size);
|
|
|
++#else
|
|
|
++ memcpy(argp, *p_argv, (*p_arg)->size);
|
|
|
++#endif
|
|
|
++ 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 hcsky anything
|
|
|
++ when it isn't needed. */
|
|
|
++ cif->bytes = (cif->bytes + 7) & ~7;
|
|
|
++
|
|
|
++ /* Set the return type flag */
|
|
|
++ switch (cif->rtype->type)
|
|
|
++ {
|
|
|
++
|
|
|
++ case FFI_TYPE_DOUBLE:
|
|
|
++ 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 if (cif->rtype->size <= 8)
|
|
|
++ /* A Composite Type not larger than 8 bytes is returned in r0, r1. */
|
|
|
++ cif->flags = (unsigned)FFI_TYPE_SINT64;
|
|
|
++ else
|
|
|
++ /* A Composite Type larger than 8 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;
|
|
|
++}
|
|
|
++
|
|
|
++/* Perform machine dependent cif processing for variadic calls */
|
|
|
++ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
|
|
|
++ unsigned int nfixedargs,
|
|
|
++ unsigned int ntotalargs)
|
|
|
++{
|
|
|
++ return ffi_prep_cif_machdep(cif);
|
|
|
++}
|
|
|
++
|
|
|
++/* Prototypes for assembly functions, in sysv.S */
|
|
|
++extern void ffi_call_SYSV (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *);
|
|
|
++
|
|
|
++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 (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
|
|
|
++ break;
|
|
|
++
|
|
|
++ default:
|
|
|
++ FFI_ASSERT(0);
|
|
|
++ break;
|
|
|
++ }
|
|
|
++ if (small_struct)
|
|
|
++#ifdef __CSKYBE__
|
|
|
++ memcpy (rvalue, ((unsigned char *)&temp + (4 - cif->rtype->size)), cif->rtype->size);
|
|
|
++#else
|
|
|
++ memcpy (rvalue, &temp, cif->rtype->size);
|
|
|
++#endif
|
|
|
++}
|
|
|
++
|
|
|
++/** 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);
|
|
|
++
|
|
|
++#ifdef __CSKYBE__
|
|
|
++ if (cif->flags == FFI_TYPE_INT && cif->rtype->type == FFI_TYPE_STRUCT) {
|
|
|
++ unsigned int tmp = 0;
|
|
|
++ tmp = *(unsigned int *)(*respp);
|
|
|
++ *(unsigned int *)(*respp) = (tmp >> ((4 - cif->rtype->size) * 8));
|
|
|
++ }
|
|
|
++#endif
|
|
|
++
|
|
|
++ return cif->flags;
|
|
|
++}
|
|
|
++
|
|
|
++
|
|
|
++static void
|
|
|
++ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
|
|
|
++ void **avalue, ffi_cif *cif)
|
|
|
++{
|
|
|
++ 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;
|
|
|
++
|
|
|
++ alignment = (*p_arg)->alignment;
|
|
|
++ if (alignment < 4)
|
|
|
++ alignment = 4;
|
|
|
++
|
|
|
++#ifdef __CSKYABIV1__
|
|
|
++ /*
|
|
|
++ * Adapt ABIV1 bug.
|
|
|
++ * If struct's size is larger than 8 bytes, then it always alignment as 4 bytes.
|
|
|
++ */
|
|
|
++ if (((*p_arg)->type == FFI_TYPE_STRUCT) && ((*p_arg)->size > 8) && (alignment == 8)) {
|
|
|
++ alignment = 4;
|
|
|
++ }
|
|
|
++#endif
|
|
|
++
|
|
|
++ /* Align if necessary */
|
|
|
++ if ((alignment - 1) & (unsigned) argp) {
|
|
|
++ argp = (char *) FFI_ALIGN(argp, alignment);
|
|
|
++ }
|
|
|
++
|
|
|
++ z = (*p_arg)->size;
|
|
|
++
|
|
|
++#ifdef __CSKYBE__
|
|
|
++ unsigned int tmp = 0;
|
|
|
++ if ((*p_arg)->size < 4) {
|
|
|
++ tmp = *(unsigned int *)argp;
|
|
|
++ memcpy(argp, ((unsigned char *)&tmp + (4 - (*p_arg)->size)), (*p_arg)->size);
|
|
|
++ }
|
|
|
++#else
|
|
|
++ /* because we're little endian, this is what it turns into. */
|
|
|
++#endif
|
|
|
++ *p_argv = (void*) argp;
|
|
|
++
|
|
|
++ p_argv++;
|
|
|
++ argp += z;
|
|
|
++ }
|
|
|
++
|
|
|
++ return;
|
|
|
++}
|
|
|
++
|
|
|
++/* How to make a trampoline. */
|
|
|
++
|
|
|
++extern unsigned char ffi_csky_trampoline[TRAMPOLINE_SIZE];
|
|
|
++
|
|
|
++/*
|
|
|
++ * Since there is no __clear_cache in libgcc in csky toolchain.
|
|
|
++ * define ffi_csky_cacheflush in sysv.S.
|
|
|
++ * void ffi_csky_cacheflush(uint32 start_addr, uint32 size, int cache)
|
|
|
++ */
|
|
|
++#define CACHEFLUSH_IN_FFI 1
|
|
|
++#if CACHEFLUSH_IN_FFI
|
|
|
++extern void ffi_csky_cacheflush(unsigned char *__tramp, unsigned int k,
|
|
|
++ int i);
|
|
|
++#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 char *insns = (unsigned char *)(CTX); \
|
|
|
++ memcpy (__tramp, ffi_csky_trampoline, TRAMPOLINE_SIZE); \
|
|
|
++ *(unsigned int*) &__tramp[TRAMPOLINE_SIZE] = __ctx; \
|
|
|
++ *(unsigned int*) &__tramp[TRAMPOLINE_SIZE + 4] = __fun; \
|
|
|
++ ffi_csky_cacheflush(&__tramp[0], TRAMPOLINE_SIZE, 3); /* Clear data mapping. */ \
|
|
|
++ ffi_csky_cacheflush(insns, TRAMPOLINE_SIZE, 3); \
|
|
|
++ /* Clear instruction \
|
|
|
++ mapping. */ \
|
|
|
++ })
|
|
|
++#else
|
|
|
++#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 char *insns = (unsigned char *)(CTX); \
|
|
|
++ memcpy (__tramp, ffi_csky_trampoline, TRAMPOLINE_SIZE); \
|
|
|
++ *(unsigned int*) &__tramp[TRAMPOLINE_SIZE] = __ctx; \
|
|
|
++ *(unsigned int*) &__tramp[TRAMPOLINE_SIZE + 4] = __fun; \
|
|
|
++ __clear_cache((&__tramp[0]), (&__tramp[TRAMPOLINE_SIZE-1])); /* Clear data mapping. */ \
|
|
|
++ __clear_cache(insns, insns + TRAMPOLINE_SIZE); \
|
|
|
++ /* Clear instruction \
|
|
|
++ mapping. */ \
|
|
|
++ })
|
|
|
++#endif
|
|
|
++
|
|
|
++/* 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)
|
|
|
++{
|
|
|
++ void (*closure_func)(ffi_closure*) = NULL;
|
|
|
++
|
|
|
++ if (cif->abi == FFI_SYSV)
|
|
|
++ closure_func = &ffi_closure_SYSV;
|
|
|
++ else
|
|
|
++ return FFI_BAD_ABI;
|
|
|
++
|
|
|
++ FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
|
|
|
++ closure_func, \
|
|
|
++ codeloc);
|
|
|
++
|
|
|
++ closure->cif = cif;
|
|
|
++ closure->user_data = user_data;
|
|
|
++ closure->fun = fun;
|
|
|
++
|
|
|
++ return FFI_OK;
|
|
|
++}
|
|
|
++
|
|
|
++
|
|
|
+diff --git a/src/csky/ffitarget.h b/src/csky/ffitarget.h
|
|
|
+new file mode 100644
|
|
|
+index 0000000..f770aac
|
|
|
+--- /dev/null
|
|
|
++++ b/src/csky/ffitarget.h
|
|
|
+@@ -0,0 +1,63 @@
|
|
|
++/* -----------------------------------------------------------------*-C-*-
|
|
|
++ ffitarget.h - Copyright (c) 2012 Anthony Green
|
|
|
++ Copyright (c) 2010 CodeSourcery
|
|
|
++ Copyright (c) 1996-2003 Red Hat, Inc.
|
|
|
++
|
|
|
++ Target configuration macros for CSKY.
|
|
|
++
|
|
|
++ 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
|
|
|
++typedef unsigned long ffi_arg;
|
|
|
++typedef signed long ffi_sarg;
|
|
|
++
|
|
|
++typedef enum ffi_abi {
|
|
|
++ FFI_FIRST_ABI = 0,
|
|
|
++ FFI_SYSV,
|
|
|
++ FFI_LAST_ABI,
|
|
|
++ FFI_DEFAULT_ABI = FFI_SYSV,
|
|
|
++} ffi_abi;
|
|
|
++#endif
|
|
|
++
|
|
|
++#ifdef __CSKYABIV2__
|
|
|
++#define FFI_ASM_ARGREG_SIZE 16
|
|
|
++#define TRAMPOLINE_SIZE 16
|
|
|
++#define FFI_TRAMPOLINE_SIZE 24
|
|
|
++#else
|
|
|
++#define FFI_ASM_ARGREG_SIZE 24
|
|
|
++#define TRAMPOLINE_SIZE 20
|
|
|
++#define FFI_TRAMPOLINE_SIZE 28
|
|
|
++#endif
|
|
|
++
|
|
|
++/* ---- Definitions for closures ----------------------------------------- */
|
|
|
++
|
|
|
++#define FFI_CLOSURES 1
|
|
|
++#define FFI_NATIVE_RAW_API 0
|
|
|
++#endif
|
|
|
+diff --git a/src/csky/sysv.S b/src/csky/sysv.S
|
|
|
+new file mode 100644
|
|
|
+index 0000000..962a796
|
|
|
+--- /dev/null
|
|
|
++++ b/src/csky/sysv.S
|
|
|
+@@ -0,0 +1,371 @@
|
|
|
++/* -----------------------------------------------------------------------
|
|
|
++ sysv.S
|
|
|
++
|
|
|
++ CSKY 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>
|
|
|
++
|
|
|
++.macro CSKY_FUNC_START name
|
|
|
++ .text
|
|
|
++ .align 2
|
|
|
++ .globl \name
|
|
|
++ .type \name, @function
|
|
|
++ \name:
|
|
|
++.endm
|
|
|
++
|
|
|
++#ifdef __CSKYABIV2__
|
|
|
++
|
|
|
++ /*
|
|
|
++ * a0: fn
|
|
|
++ * a1: &ecif
|
|
|
++ * a2: cif->bytes
|
|
|
++ * a3: fig->flags
|
|
|
++ * sp+0: ecif.rvalue
|
|
|
++ */
|
|
|
++CSKY_FUNC_START ffi_call_SYSV
|
|
|
++ /* Save registers */
|
|
|
++ .cfi_startproc
|
|
|
++ subi sp, 28
|
|
|
++ .cfi_def_cfa_offset 28
|
|
|
++ stw a0, (sp, 0x0)
|
|
|
++ .cfi_offset 0, -28
|
|
|
++ stw a1, (sp, 0x4)
|
|
|
++ .cfi_offset 1, -24
|
|
|
++ stw a2, (sp, 0x8)
|
|
|
++ .cfi_offset 2, -20
|
|
|
++ stw a3, (sp, 0xC)
|
|
|
++ .cfi_offset 3, -16
|
|
|
++ stw l0, (sp, 0x10)
|
|
|
++ .cfi_offset 4, -12
|
|
|
++ stw l1, (sp, 0x14)
|
|
|
++ .cfi_offset 5, -8
|
|
|
++ stw lr, (sp, 0x18)
|
|
|
++ .cfi_offset 15, -4
|
|
|
++
|
|
|
++ mov l0, sp
|
|
|
++ .cfi_def_cfa_register 4
|
|
|
++
|
|
|
++ /* Make room for all of the new args. */
|
|
|
++ subu sp, sp, a2
|
|
|
++
|
|
|
++ /* Place all of the ffi_prep_args in position */
|
|
|
++ mov a0, sp
|
|
|
++ /* a1 already set */
|
|
|
++
|
|
|
++ /* Call ffi_prep_args(stack, &ecif) */
|
|
|
++ jsri ffi_prep_args
|
|
|
++
|
|
|
++ /* move first 4 parameters in registers */
|
|
|
++ ldw a0, (sp, 0x0)
|
|
|
++ ldw a1, (sp, 0x4)
|
|
|
++ ldw a2, (sp, 0x8)
|
|
|
++ ldw a3, (sp, 0xC)
|
|
|
++
|
|
|
++ /* and adjust stack */
|
|
|
++ subu lr, l0, sp /* cif->bytes == l0 - sp */
|
|
|
++ cmphsi lr, 16
|
|
|
++ movi l1, 16
|
|
|
++ movt lr, l1
|
|
|
++ addu sp, sp, lr
|
|
|
++
|
|
|
++ ldw l1, (l0, 0) /* load fn() in advance */
|
|
|
++
|
|
|
++ /* call (fn) (...) */
|
|
|
++ jsr l1
|
|
|
++
|
|
|
++ /* Remove the space we pushed for the args */
|
|
|
++ mov sp, l0
|
|
|
++
|
|
|
++ /* Load r2 with the pointer to storage for the return value */
|
|
|
++ ldw a2, (sp, 0x1C)
|
|
|
++
|
|
|
++ /* Load r3 with the return type code */
|
|
|
++ ldw a3, (sp, 0xC)
|
|
|
++
|
|
|
++ /* If the return value pointer is NULL, assume no return value. */
|
|
|
++ cmpnei a2, 0
|
|
|
++ bf .Lepilogue
|
|
|
++
|
|
|
++ cmpnei a3, FFI_TYPE_STRUCT
|
|
|
++ bf .Lepilogue
|
|
|
++
|
|
|
++ /* return INT64 */
|
|
|
++ cmpnei a3, FFI_TYPE_SINT64
|
|
|
++ bt .Lretint
|
|
|
++ /* stw a0, (a2, 0x0) at .Lretint */
|
|
|
++ stw a1, (a2, 0x4)
|
|
|
++
|
|
|
++.Lretint:
|
|
|
++ /* return INT */
|
|
|
++ stw a0, (a2, 0x0)
|
|
|
++
|
|
|
++.Lepilogue:
|
|
|
++ ldw a0, (sp, 0x0)
|
|
|
++ ldw a1, (sp, 0x4)
|
|
|
++ ldw a2, (sp, 0x8)
|
|
|
++ ldw a3, (sp, 0xC)
|
|
|
++ ldw l0, (sp, 0x10)
|
|
|
++ ldw l1, (sp, 0x14)
|
|
|
++ ldw lr, (sp, 0x18)
|
|
|
++ addi sp, sp, 28
|
|
|
++ rts
|
|
|
++ .cfi_endproc
|
|
|
++ .size ffi_call_SYSV, .-ffi_call_SYSV
|
|
|
++
|
|
|
++
|
|
|
++ /*
|
|
|
++ * unsigned int FFI_HIDDEN
|
|
|
++ * ffi_closure_SYSV_inner (closure, respp, args)
|
|
|
++ * ffi_closure *closure;
|
|
|
++ * void **respp;
|
|
|
++ * void *args;
|
|
|
++ */
|
|
|
++CSKY_FUNC_START ffi_closure_SYSV
|
|
|
++ .cfi_startproc
|
|
|
++ mov a2, sp
|
|
|
++ addi a1, sp, 16
|
|
|
++ subi sp, sp, 24
|
|
|
++ .cfi_def_cfa_offset 40
|
|
|
++ stw a1, (sp, 0x10)
|
|
|
++ .cfi_offset 1, -24
|
|
|
++ stw lr, (sp, 0x14)
|
|
|
++ .cfi_offset 15, -20
|
|
|
++ stw sp, (sp, 0x8)
|
|
|
++ addi a1, sp, 8
|
|
|
++ jsri ffi_closure_SYSV_inner
|
|
|
++ ldw a0, (sp, 0x0)
|
|
|
++ /*
|
|
|
++ * if FFI_TYPE_SINT64, need a1.
|
|
|
++ * if FFI_TYPE_INT, ignore a1.
|
|
|
++ */
|
|
|
++ ldw a1, (sp, 0x4)
|
|
|
++
|
|
|
++ ldw lr, (sp, 0x14)
|
|
|
++ addi sp, sp, 40
|
|
|
++ rts
|
|
|
++ .cfi_endproc
|
|
|
++ .size ffi_closure_SYSV, .-ffi_closure_SYSV
|
|
|
++
|
|
|
++CSKY_FUNC_START ffi_csky_trampoline
|
|
|
++ subi sp, sp, 16
|
|
|
++ stw a0, (sp, 0x0)
|
|
|
++ stw a1, (sp, 0x4)
|
|
|
++ stw a2, (sp, 0x8)
|
|
|
++ stw a3, (sp, 0xC)
|
|
|
++ lrw a0, [.Lctx]
|
|
|
++ lrw a1, [.Lfun]
|
|
|
++ jmp a1
|
|
|
++.Lctx:
|
|
|
++ mov a0, a0
|
|
|
++ mov a0, a0
|
|
|
++.Lfun:
|
|
|
++
|
|
|
++ .size ffi_csky_trampoline, .-ffi_csky_trampoline
|
|
|
++
|
|
|
++CSKY_FUNC_START ffi_csky_cacheflush
|
|
|
++ mov t0, r7
|
|
|
++ movi r7, 123
|
|
|
++ trap 0
|
|
|
++ mov r7, t0
|
|
|
++ rts
|
|
|
++
|
|
|
++ .size ffi_csky_cacheflush, .-ffi_csky_cacheflush
|
|
|
++
|
|
|
++#else /* !__CSKYABIV2__ */
|
|
|
++
|
|
|
++ /*
|
|
|
++ * a0: fn
|
|
|
++ * a1: &ecif
|
|
|
++ * a2: cif->bytes
|
|
|
++ * a3: fig->flags
|
|
|
++ * a4: ecif.rvalue
|
|
|
++ */
|
|
|
++CSKY_FUNC_START ffi_call_SYSV
|
|
|
++ /* Save registers */
|
|
|
++ .cfi_startproc
|
|
|
++ subi sp, 32
|
|
|
++ subi sp, 8
|
|
|
++ .cfi_def_cfa_offset 40
|
|
|
++ stw a0, (sp, 0x0)
|
|
|
++ .cfi_offset 2, -40
|
|
|
++ stw a1, (sp, 0x4)
|
|
|
++ .cfi_offset 3, -36
|
|
|
++ stw a2, (sp, 0x8)
|
|
|
++ .cfi_offset 4, -32
|
|
|
++ stw a3, (sp, 0xC)
|
|
|
++ .cfi_offset 5, -28
|
|
|
++ stw a4, (sp, 0x10)
|
|
|
++ .cfi_offset 6, -24
|
|
|
++ stw a5, (sp, 0x14)
|
|
|
++ .cfi_offset 7, -20
|
|
|
++ stw l0, (sp, 0x18)
|
|
|
++ .cfi_offset 8, -16
|
|
|
++ stw l1, (sp, 0x1C)
|
|
|
++ .cfi_offset 9, -12
|
|
|
++ stw lr, (sp, 0x20)
|
|
|
++ .cfi_offset 15, -8
|
|
|
++
|
|
|
++ mov l0, sp
|
|
|
++ .cfi_def_cfa_register 8
|
|
|
++
|
|
|
++ /* Make room for all of the new args. */
|
|
|
++ subu sp, sp, a2
|
|
|
++
|
|
|
++ /* Place all of the ffi_prep_args in position */
|
|
|
++ mov a0, sp
|
|
|
++ /* a1 already set */
|
|
|
++
|
|
|
++ /* Call ffi_prep_args(stack, &ecif) */
|
|
|
++ jsri ffi_prep_args
|
|
|
++
|
|
|
++ /* move first 4 parameters in registers */
|
|
|
++ ldw a0, (sp, 0x0)
|
|
|
++ ldw a1, (sp, 0x4)
|
|
|
++ ldw a2, (sp, 0x8)
|
|
|
++ ldw a3, (sp, 0xC)
|
|
|
++ ldw a4, (sp, 0x10)
|
|
|
++ ldw a5, (sp, 0x14)
|
|
|
++
|
|
|
++ /* and adjust stack */
|
|
|
++ mov lr, l0
|
|
|
++ subu lr, sp /* cif->bytes == l0 - sp */
|
|
|
++ movi l1, 24
|
|
|
++ cmphs lr, l1
|
|
|
++ movt lr, l1
|
|
|
++ addu sp, sp, lr
|
|
|
++
|
|
|
++ ldw l1, (l0, 0) /* load fn() in advance */
|
|
|
++
|
|
|
++ /* call (fn) (...) */
|
|
|
++ jsr l1
|
|
|
++
|
|
|
++ /* Remove the space we pushed for the args */
|
|
|
++ mov sp, l0
|
|
|
++
|
|
|
++ /* Load r2 with the pointer to storage for the return value */
|
|
|
++ ldw a2, (sp, 0x10)
|
|
|
++
|
|
|
++ /* Load r3 with the return type code */
|
|
|
++ ldw a3, (sp, 0xC)
|
|
|
++
|
|
|
++ /* If the return value pointer is NULL, assume no return value. */
|
|
|
++ cmpnei a2, 0
|
|
|
++ bf .Lepilogue
|
|
|
++
|
|
|
++ cmpnei a3, FFI_TYPE_STRUCT
|
|
|
++ bf .Lepilogue
|
|
|
++
|
|
|
++ /* return INT64 */
|
|
|
++ cmpnei a3, FFI_TYPE_SINT64
|
|
|
++ bt .Lretint
|
|
|
++ /* stw a0, (a2, 0x0) at .Lretint */
|
|
|
++ stw a1, (a2, 0x4)
|
|
|
++
|
|
|
++.Lretint:
|
|
|
++ /* return INT */
|
|
|
++ stw a0, (a2, 0x0)
|
|
|
++
|
|
|
++.Lepilogue:
|
|
|
++ ldw a0, (sp, 0x0)
|
|
|
++ ldw a1, (sp, 0x4)
|
|
|
++ ldw a2, (sp, 0x8)
|
|
|
++ ldw a3, (sp, 0xC)
|
|
|
++ ldw a4, (sp, 0x10)
|
|
|
++ ldw a5, (sp, 0x14)
|
|
|
++ ldw l0, (sp, 0x18)
|
|
|
++ ldw l1, (sp, 0x1C)
|
|
|
++ ldw lr, (sp, 0x20)
|
|
|
++ addi sp, sp, 32
|
|
|
++ addi sp, sp, 8
|
|
|
++ rts
|
|
|
++ .cfi_endproc
|
|
|
++
|
|
|
++ .size ffi_call_SYSV, .-ffi_call_SYSV
|
|
|
++
|
|
|
++
|
|
|
++ /*
|
|
|
++ * unsigned int FFI_HIDDEN
|
|
|
++ * ffi_closure_SYSV_inner (closure, respp, args)
|
|
|
++ * ffi_closure *closure;
|
|
|
++ * void **respp;
|
|
|
++ * void *args;
|
|
|
++ */
|
|
|
++CSKY_FUNC_START ffi_closure_SYSV
|
|
|
++ .cfi_startproc
|
|
|
++ mov a2, sp
|
|
|
++ mov a1, sp
|
|
|
++ addi a1, 24
|
|
|
++ subi sp, sp, 24
|
|
|
++ .cfi_def_cfa_offset 48
|
|
|
++ stw a1, (sp, 0x10)
|
|
|
++ .cfi_offset 3, -32
|
|
|
++ stw lr, (sp, 0x14)
|
|
|
++ .cfi_offset 15, -28
|
|
|
++ stw sp, (sp, 0x8)
|
|
|
++ mov a1, sp
|
|
|
++ addi a1, 8
|
|
|
++ jsri ffi_closure_SYSV_inner
|
|
|
++ ldw a0, (sp, 0x0)
|
|
|
++ /*
|
|
|
++ * if FFI_TYPE_SINT64, need a1.
|
|
|
++ * if FFI_TYPE_INT, ignore a1.
|
|
|
++ */
|
|
|
++ ldw a1, (sp, 0x4)
|
|
|
++
|
|
|
++ ldw lr, (sp, 0x14)
|
|
|
++ addi sp, sp, 24
|
|
|
++ addi sp, sp, 24
|
|
|
++ rts
|
|
|
++ .cfi_endproc
|
|
|
++
|
|
|
++ .size ffi_closure_SYSV, .-ffi_closure_SYSV
|
|
|
++
|
|
|
++CSKY_FUNC_START ffi_csky_trampoline
|
|
|
++ subi sp, 24
|
|
|
++ stw a0, (sp, 0x0)
|
|
|
++ stw a1, (sp, 0x4)
|
|
|
++ stw a2, (sp, 0x8)
|
|
|
++ stw a3, (sp, 0xC)
|
|
|
++ stw a4, (sp, 0x10)
|
|
|
++ stw a5, (sp, 0x14)
|
|
|
++ lrw a0, [.Lctx]
|
|
|
++ lrw a1, [.Lfun]
|
|
|
++ jmp a1
|
|
|
++.Lctx:
|
|
|
++ mov a0, a0
|
|
|
++ mov a0, a0
|
|
|
++.Lfun:
|
|
|
++
|
|
|
++ .size ffi_csky_trampoline, .-ffi_csky_trampoline
|
|
|
++
|
|
|
++CSKY_FUNC_START ffi_csky_cacheflush
|
|
|
++ lrw r1, 123
|
|
|
++ trap 0
|
|
|
++ rts
|
|
|
++
|
|
|
++ .size ffi_csky_cacheflush, .-ffi_csky_cacheflush
|
|
|
++
|
|
|
++#endif /* __CSKYABIV2__ */
|