* [PATCH] package/libffi: Add csky cpu support
@ 2020-03-15 9:32 Ma Jun
2020-03-24 13:41 ` Anthony Green
2020-06-28 6:26 ` MaJun
0 siblings, 2 replies; 4+ messages in thread
From: Ma Jun @ 2020-03-15 9:32 UTC (permalink / raw)
To: libffi-discuss; +Cc: majun258, linux-csky, wenmeng_zhang
This patch added the support for csky cpu architecture
Signed-off-by: Zhang Wenmeng <wenmeng_zhang@c-sky.com>
Signed-off-by: Ma Jun <majun258@linux.alibaba.com>
---
Makefile.am | 2 +
README.md | 1 +
configure.host | 5 +
src/csky/ffi.c | 395 +++++++++++++++++++++++++++++++++++++++++++
src/csky/ffitarget.h | 63 +++++++
src/csky/sysv.S | 371 ++++++++++++++++++++++++++++++++++++++++
6 files changed, 837 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/Makefile.am b/Makefile.am
index f83e444..e528ffd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -53,6 +53,7 @@ noinst_HEADERS = \
src/avr32/ffitarget.h \
src/bfin/ffitarget.h \
src/cris/ffitarget.h \
+ src/csky/ffitarget.h \
src/frv/ffitarget.h \
src/ia64/ffitarget.h src/ia64/ia64_flags.h \
src/m32r/ffitarget.h \
@@ -85,6 +86,7 @@ EXTRA_libffi_la_SOURCES = \
src/avr32/ffi.c src/avr32/sysv.S \
src/bfin/ffi.c src/bfin/sysv.S \
src/cris/ffi.c src/cris/sysv.S \
+ src/csky/ffi.c src/csky/sysv.S \
src/frv/ffi.c src/frv/eabi.S \
src/ia64/ffi.c src/ia64/unix.S \
src/m32r/ffi.c src/m32r/sysv.S \
diff --git a/README.md b/README.md
index 3caf2fa..bdfe880 100644
--- a/README.md
+++ b/README.md
@@ -58,6 +58,7 @@ tested:
| ARM | iOS | GCC |
| AVR32 | Linux | GCC |
| Blackfin | uClinux | GCC |
+| CSKY | Linux | GCC |
| HPPA | HPUX | GCC |
| IA-64 | Linux | GCC |
| M68K | FreeMiNT | GCC |
diff --git a/configure.host b/configure.host
index 7634c3a..9201cd4 100644
--- a/configure.host
+++ b/configure.host
@@ -43,6 +43,11 @@ case "${host}" in
SOURCES="ffi.c sysv.S"
;;
+ csky-*-*)
+ TARGET=CSKY; TARGETDIR=csky
+ SOURCES="ffi.c sysv.S"
+ ;;
+
frv-*-*)
TARGET=FRV; TARGETDIR=frv
SOURCES="ffi.c eabi.S"
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__ */
--
2.17.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] package/libffi: Add csky cpu support
2020-03-15 9:32 [PATCH] package/libffi: Add csky cpu support Ma Jun
@ 2020-03-24 13:41 ` Anthony Green
2020-07-06 12:02 ` 回复:[PATCH] " MaJun
2020-06-28 6:26 ` MaJun
1 sibling, 1 reply; 4+ messages in thread
From: Anthony Green @ 2020-03-24 13:41 UTC (permalink / raw)
To: Ma Jun; +Cc: libffi-discuss, wenmeng_zhang, linux-csky
Thank you for this patch. I have merged it into a branch on github for now:
https://github.com/libffi/libffi/commit/54b81a5167de713c7bba0cfde5ccea3398b69128
There's no opportunity to test the code without a compiler or simulator,
but I'm willing to merge in the absence of those. Eventually we will need
a simulator so we can test on travis-ci.
The source files require a copyright notice. Would adding something like
this work?...
ffi.c - Copyright (C) 2020 Alibaba
I would also like to adjust some of the spacing from 4-space tabs to
2-space tabs. I can make that change, or you can resubmit. Other than
that, I'm ok with these changes.
Thanks,
AG
On Mon, Mar 23, 2020 at 3:04 AM Ma Jun via Libffi-discuss <
libffi-discuss@sourceware.org> wrote:
> This patch added the support for csky cpu architecture
>
> Signed-off-by: Zhang Wenmeng <wenmeng_zhang@c-sky.com>
> Signed-off-by: Ma Jun <majun258@linux.alibaba.com>
> ---
> Makefile.am | 2 +
> README.md | 1 +
> configure.host | 5 +
> src/csky/ffi.c | 395 +++++++++++++++++++++++++++++++++++++++++++
> src/csky/ffitarget.h | 63 +++++++
> src/csky/sysv.S | 371 ++++++++++++++++++++++++++++++++++++++++
> 6 files changed, 837 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/Makefile.am b/Makefile.am
> index f83e444..e528ffd 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -53,6 +53,7 @@ noinst_HEADERS = \
> src/avr32/ffitarget.h \
> src/bfin/ffitarget.h \
> src/cris/ffitarget.h \
> + src/csky/ffitarget.h \
> src/frv/ffitarget.h \
> src/ia64/ffitarget.h src/ia64/ia64_flags.h \
> src/m32r/ffitarget.h \
> @@ -85,6 +86,7 @@ EXTRA_libffi_la_SOURCES = \
> src/avr32/ffi.c src/avr32/sysv.S \
> src/bfin/ffi.c src/bfin/sysv.S \
> src/cris/ffi.c src/cris/sysv.S \
> + src/csky/ffi.c src/csky/sysv.S \
> src/frv/ffi.c src/frv/eabi.S \
> src/ia64/ffi.c src/ia64/unix.S \
> src/m32r/ffi.c src/m32r/sysv.S \
> diff --git a/README.md b/README.md
> index 3caf2fa..bdfe880 100644
> --- a/README.md
> +++ b/README.md
> @@ -58,6 +58,7 @@ tested:
> | ARM | iOS | GCC |
> | AVR32 | Linux | GCC |
> | Blackfin | uClinux | GCC |
> +| CSKY | Linux | GCC |
> | HPPA | HPUX | GCC |
> | IA-64 | Linux | GCC |
> | M68K | FreeMiNT | GCC |
> diff --git a/configure.host b/configure.host
> index 7634c3a..9201cd4 100644
> --- a/configure.host
> +++ b/configure.host
> @@ -43,6 +43,11 @@ case "${host}" in
> SOURCES="ffi.c sysv.S"
> ;;
>
> + csky-*-*)
> + TARGET=CSKY; TARGETDIR=csky
> + SOURCES="ffi.c sysv.S"
> + ;;
> +
> frv-*-*)
> TARGET=FRV; TARGETDIR=frv
> SOURCES="ffi.c eabi.S"
> 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__ */
> --
> 2.17.1
>
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* 回复:[PATCH] package/libffi: Add csky cpu support
2020-03-15 9:32 [PATCH] package/libffi: Add csky cpu support Ma Jun
2020-03-24 13:41 ` Anthony Green
@ 2020-06-28 6:26 ` MaJun
1 sibling, 0 replies; 4+ messages in thread
From: MaJun @ 2020-06-28 6:26 UTC (permalink / raw)
To: libffi-discuss, green; +Cc: linux-csky, wenmeng_zhang
Hi Mr Green:
Could you help to review this patch?
Thanks !
------------------------------------------------------------------
发件人:Ma Jun <majun258@linux.alibaba.com>
发送时间:2020年3月23日(星期一) 15:04
收件人:libffi-discuss <libffi-discuss@sourceware.org>
抄 送:majun258 <majun258@linux.alibaba.com>; linux-csky <linux-csky@vger.kernel.org>; wenmeng_zhang <wenmeng_zhang@c-sky.com>
主 题:[PATCH] package/libffi: Add csky cpu support
This patch added the support for csky cpu architecture
Signed-off-by: Zhang Wenmeng <wenmeng_zhang@c-sky.com>
Signed-off-by: Ma Jun <majun258@linux.alibaba.com>
---
Makefile.am | 2 +
README.md | 1 +
configure.host | 5 +
src/csky/ffi.c | 395 +++++++++++++++++++++++++++++++++++++++++++
src/csky/ffitarget.h | 63 +++++++
src/csky/sysv.S | 371 ++++++++++++++++++++++++++++++++++++++++
6 files changed, 837 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/Makefile.am b/Makefile.am
index f83e444..e528ffd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -53,6 +53,7 @@ noinst_HEADERS = \
src/avr32/ffitarget.h \
src/bfin/ffitarget.h \
src/cris/ffitarget.h \
+ src/csky/ffitarget.h \
src/frv/ffitarget.h \
src/ia64/ffitarget.h src/ia64/ia64_flags.h \
src/m32r/ffitarget.h \
@@ -85,6 +86,7 @@ EXTRA_libffi_la_SOURCES = \
src/avr32/ffi.c src/avr32/sysv.S \
src/bfin/ffi.c src/bfin/sysv.S \
src/cris/ffi.c src/cris/sysv.S \
+ src/csky/ffi.c src/csky/sysv.S \
src/frv/ffi.c src/frv/eabi.S \
src/ia64/ffi.c src/ia64/unix.S \
src/m32r/ffi.c src/m32r/sysv.S \
diff --git a/README.md b/README.md
index 3caf2fa..bdfe880 100644
--- a/README.md
+++ b/README.md
@@ -58,6 +58,7 @@ tested:
| ARM | iOS | GCC |
| AVR32 | Linux | GCC |
| Blackfin | uClinux | GCC |
+| CSKY | Linux | GCC |
| HPPA | HPUX | GCC |
| IA-64 | Linux | GCC |
| M68K | FreeMiNT | GCC |
diff --git a/configure.host b/configure.host
index 7634c3a..9201cd4 100644
--- a/configure.host
+++ b/configure.host
@@ -43,6 +43,11 @@ case "${host}" in
SOURCES="ffi.c sysv.S"
;;
+ csky-*-*)
+ TARGET=CSKY; TARGETDIR=csky
+ SOURCES="ffi.c sysv.S"
+ ;;
+
frv-*-*)
TARGET=FRV; TARGETDIR=frv
SOURCES="ffi.c eabi.S"
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__ */
--
2.17.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* 回复:[PATCH] package/libffi: Add csky cpu support
2020-03-24 13:41 ` Anthony Green
@ 2020-07-06 12:02 ` MaJun
0 siblings, 0 replies; 4+ messages in thread
From: MaJun @ 2020-07-06 12:02 UTC (permalink / raw)
To: Anthony Green; +Cc: libffi-discuss, wenmeng_zhang, linux-csky
Hi Mr. Green:
Sorry for missing this reply. I will resend a new patch based on your suggestion.
Thanks
------------------------------------------------------------------
发件人:Anthony Green <green@moxielogic.com>
发送时间:2020年3月24日(星期二) 21:41
收件人:Ma Jun <majun258@linux.alibaba.com>
抄 送:libffi-discuss <libffi-discuss@sourceware.org>; wenmeng_zhang <wenmeng_zhang@c-sky.com>; linux-csky <linux-csky@vger.kernel.org>
主 题:Re: [PATCH] package/libffi: Add csky cpu support
Thank you for this patch. I have merged it into a branch on github for now:
https://github.com/libffi/libffi/commit/54b81a5167de713c7bba0cfde5ccea3398b69128
There's no opportunity to test the code without a compiler or simulator, but I'm willing to merge in the absence of those. Eventually we will need a simulator so we can test on travis-ci.
The source files require a copyright notice. Would adding something like this work?...
ffi.c - Copyright (C) 2020 Alibaba
I would also like to adjust some of the spacing from 4-space tabs to 2-space tabs. I can make that change, or you can resubmit. Other than that, I'm ok with these changes.
Thanks,
AG
On Mon, Mar 23, 2020 at 3:04 AM Ma Jun via Libffi-discuss <libffi-discuss@sourceware.org> wrote:
This patch added the support for csky cpu architecture
Signed-off-by: Zhang Wenmeng <wenmeng_zhang@c-sky.com>
Signed-off-by: Ma Jun <majun258@linux.alibaba.com>
---
Makefile.am | 2 +
README.md | 1 +
configure.host | 5 +
src/csky/ffi.c | 395 +++++++++++++++++++++++++++++++++++++++++++
src/csky/ffitarget.h | 63 +++++++
src/csky/sysv.S | 371 ++++++++++++++++++++++++++++++++++++++++
6 files changed, 837 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/Makefile.am b/Makefile.am
index f83e444..e528ffd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -53,6 +53,7 @@ noinst_HEADERS = \
src/avr32/ffitarget.h \
src/bfin/ffitarget.h \
src/cris/ffitarget.h \
+ src/csky/ffitarget.h \
src/frv/ffitarget.h \
src/ia64/ffitarget.h src/ia64/ia64_flags.h \
src/m32r/ffitarget.h \
@@ -85,6 +86,7 @@ EXTRA_libffi_la_SOURCES = \
src/avr32/ffi.c src/avr32/sysv.S \
src/bfin/ffi.c src/bfin/sysv.S \
src/cris/ffi.c src/cris/sysv.S \
+ src/csky/ffi.c src/csky/sysv.S \
src/frv/ffi.c src/frv/eabi.S \
src/ia64/ffi.c src/ia64/unix.S \
src/m32r/ffi.c src/m32r/sysv.S \
diff --git a/README.md b/README.md
index 3caf2fa..bdfe880 100644
--- a/README.md
+++ b/README.md
@@ -58,6 +58,7 @@ tested:
| ARM | iOS | GCC |
| AVR32 | Linux | GCC |
| Blackfin | uClinux | GCC |
+| CSKY | Linux | GCC |
| HPPA | HPUX | GCC |
| IA-64 | Linux | GCC |
| M68K | FreeMiNT | GCC |
diff --git a/configure.host b/configure.host
index 7634c3a..9201cd4 100644
--- a/configure.host
+++ b/configure.host
@@ -43,6 +43,11 @@ case "${host}" in
SOURCES="ffi.c sysv.S"
;;
+ csky-*-*)
+ TARGET=CSKY; TARGETDIR=csky
+ SOURCES="ffi.c sysv.S"
+ ;;
+
frv-*-*)
TARGET=FRV; TARGETDIR=frv
SOURCES="ffi.c eabi.S"
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__ */
--
2.17.1
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2020-07-06 12:02 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-15 9:32 [PATCH] package/libffi: Add csky cpu support Ma Jun
2020-03-24 13:41 ` Anthony Green
2020-07-06 12:02 ` 回复:[PATCH] " MaJun
2020-06-28 6:26 ` MaJun
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).