From c66eadc032d38205bdf9b53b8580ffcba9623270 Mon Sep 17 00:00:00 2001 From: swcompiler Date: Mon, 25 Nov 2024 16:51:39 +0800 Subject: [PATCH 07/16] Sw64 Port: libffi --- libffi/Makefile.in | 23 +- libffi/configure.host | 7 + libffi/src/sw_64/ffi.c | 516 +++++++++++++++++++++++++++++++++++ libffi/src/sw_64/ffitarget.h | 60 ++++ libffi/src/sw_64/internal.h | 23 ++ libffi/src/sw_64/sysv.S | 281 +++++++++++++++++++ libffi/src/types.c | 4 +- 7 files changed, 910 insertions(+), 4 deletions(-) create mode 100644 libffi/src/sw_64/ffi.c create mode 100644 libffi/src/sw_64/ffitarget.h create mode 100644 libffi/src/sw_64/internal.h create mode 100644 libffi/src/sw_64/sysv.S diff --git a/libffi/Makefile.in b/libffi/Makefile.in index 5524a6a57..217ce305e 100644 --- a/libffi/Makefile.in +++ b/libffi/Makefile.in @@ -548,6 +548,7 @@ noinst_HEADERS = src/aarch64/ffitarget.h src/aarch64/internal.h \ src/s390/ffitarget.h src/s390/internal.h src/sh/ffitarget.h \ src/sh64/ffitarget.h src/sparc/ffitarget.h \ src/sparc/internal.h src/tile/ffitarget.h src/vax/ffitarget.h \ + src/sw_64/ffitarget.h src/sw_64/internal.h \ src/x86/ffitarget.h src/x86/internal.h src/x86/internal64.h \ src/x86/asmnames.h src/xtensa/ffitarget.h src/dlmalloc.c \ src/kvx/ffitarget.h @@ -576,6 +577,7 @@ EXTRA_libffi_la_SOURCES = src/aarch64/ffi.c src/aarch64/sysv.S \ src/s390/sysv.S src/sh/ffi.c src/sh/sysv.S src/sh64/ffi.c \ src/sh64/sysv.S src/sparc/ffi.c src/sparc/ffi64.c \ src/sparc/v8.S src/sparc/v9.S src/tile/ffi.c src/tile/tile.S \ + src/sw_64/ffi.c src/sw_64/sysv.S \ src/vax/ffi.c src/vax/elfbsd.S src/x86/ffi.c src/x86/sysv.S \ src/x86/ffiw64.c src/x86/win64.S src/x86/ffi64.c \ src/x86/unix64.S src/x86/sysv_intel.S src/x86/win64_intel.S \ @@ -1012,6 +1014,16 @@ src/sparc/v8.lo: src/sparc/$(am__dirstamp) \ src/sparc/$(DEPDIR)/$(am__dirstamp) src/sparc/v9.lo: src/sparc/$(am__dirstamp) \ src/sparc/$(DEPDIR)/$(am__dirstamp) +src/sw_64/$(am__dirstamp): + @$(MKDIR_P) src/sw_64 + @: > src/sw_64/$(am__dirstamp) +src/sw_64/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/sw_64/$(DEPDIR) + @: > src/sw_64/$(DEPDIR)/$(am__dirstamp) +src/sw_64/ffi.lo: src/sw_64/$(am__dirstamp) \ + src/sw_64/$(DEPDIR)/$(am__dirstamp) +src/sw_64/sysv.lo: src/sw_64/$(am__dirstamp) \ + src/sw_64/$(DEPDIR)/$(am__dirstamp) src/tile/$(am__dirstamp): @$(MKDIR_P) src/tile @: > src/tile/$(am__dirstamp) @@ -1139,6 +1151,8 @@ mostlyclean-compile: -rm -f src/sh64/*.lo -rm -f src/sparc/*.$(OBJEXT) -rm -f src/sparc/*.lo + -rm -f src/sw_64/*.$(OBJEXT) + -rm -f src/sw_64/*.lo -rm -f src/tile/*.$(OBJEXT) -rm -f src/tile/*.lo -rm -f src/vax/*.$(OBJEXT) @@ -1228,6 +1242,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/sparc/$(DEPDIR)/ffi64.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/sparc/$(DEPDIR)/v8.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/sparc/$(DEPDIR)/v9.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/sw_64/$(DEPDIR)/ffi.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/sw_64/$(DEPDIR)/sysv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tile/$(DEPDIR)/ffi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tile/$(DEPDIR)/tile.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/vax/$(DEPDIR)/elfbsd.Plo@am__quote@ @@ -1324,6 +1340,7 @@ clean-libtool: -rm -rf src/sh/.libs src/sh/_libs -rm -rf src/sh64/.libs src/sh64/_libs -rm -rf src/sparc/.libs src/sparc/_libs + -rm -rf src/sw_64/.libs src/sw_64/_libs -rm -rf src/tile/.libs src/tile/_libs -rm -rf src/vax/.libs src/vax/_libs -rm -rf src/x86/.libs src/x86/_libs @@ -1690,6 +1707,8 @@ distclean-generic: -rm -f src/sh64/$(am__dirstamp) -rm -f src/sparc/$(DEPDIR)/$(am__dirstamp) -rm -f src/sparc/$(am__dirstamp) + -rm -f src/sw_64/$(DEPDIR)/$(am__dirstamp) + -rm -f src/sw_64/$(am__dirstamp) -rm -f src/tile/$(DEPDIR)/$(am__dirstamp) -rm -f src/tile/$(am__dirstamp) -rm -f src/vax/$(DEPDIR)/$(am__dirstamp) @@ -1712,7 +1731,7 @@ clean-am: clean-aminfo clean-generic clean-libtool clean-local \ distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -rf src/$(DEPDIR) src/aarch64/$(DEPDIR) src/alpha/$(DEPDIR) src/arc/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/bfin/$(DEPDIR) src/cris/$(DEPDIR) src/csky/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/kvx/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/m88k/$(DEPDIR) src/metag/$(DEPDIR) src/microblaze/$(DEPDIR) src/mips/$(DEPDIR) src/moxie/$(DEPDIR) src/nios2/$(DEPDIR) src/or1k/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/riscv/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/tile/$(DEPDIR) src/vax/$(DEPDIR) src/x86/$(DEPDIR) src/xtensa/$(DEPDIR) + -rm -rf src/$(DEPDIR) src/aarch64/$(DEPDIR) src/alpha/$(DEPDIR) src/arc/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/bfin/$(DEPDIR) src/cris/$(DEPDIR) src/csky/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/kvx/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/m88k/$(DEPDIR) src/metag/$(DEPDIR) src/microblaze/$(DEPDIR) src/mips/$(DEPDIR) src/moxie/$(DEPDIR) src/nios2/$(DEPDIR) src/or1k/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/riscv/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/sw_64/$(DEPDIR) src/tile/$(DEPDIR) src/vax/$(DEPDIR) src/x86/$(DEPDIR) src/xtensa/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-libtool distclean-local distclean-tags @@ -1851,7 +1870,7 @@ installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache - -rm -rf src/$(DEPDIR) src/aarch64/$(DEPDIR) src/alpha/$(DEPDIR) src/arc/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/bfin/$(DEPDIR) src/cris/$(DEPDIR) src/csky/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/kvx/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/m88k/$(DEPDIR) src/metag/$(DEPDIR) src/microblaze/$(DEPDIR) src/mips/$(DEPDIR) src/moxie/$(DEPDIR) src/nios2/$(DEPDIR) src/or1k/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/riscv/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/tile/$(DEPDIR) src/vax/$(DEPDIR) src/x86/$(DEPDIR) src/xtensa/$(DEPDIR) + -rm -rf src/$(DEPDIR) src/aarch64/$(DEPDIR) src/alpha/$(DEPDIR) src/arc/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/bfin/$(DEPDIR) src/cris/$(DEPDIR) src/csky/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/kvx/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/m88k/$(DEPDIR) src/metag/$(DEPDIR) src/microblaze/$(DEPDIR) src/mips/$(DEPDIR) src/moxie/$(DEPDIR) src/nios2/$(DEPDIR) src/or1k/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/riscv/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/sw_64/$(DEPDIR) src/tile/$(DEPDIR) src/vax/$(DEPDIR) src/x86/$(DEPDIR) src/xtensa/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-aminfo \ maintainer-clean-generic maintainer-clean-local \ diff --git a/libffi/configure.host b/libffi/configure.host index 268267183..200f2d415 100644 --- a/libffi/configure.host +++ b/libffi/configure.host @@ -247,6 +247,13 @@ case "${host}" in SOURCES="ffi.c ffi64.c v8.S v9.S" ;; + sw_64*-*-*) + TARGET=SW_64; TARGETDIR=sw_64; + # Support 128-bit long double, changeable via command-line switch. + HAVE_LONG_DOUBLE='defined(__LONG_DOUBLE_128__)' + SOURCES="ffi.c sysv.S" + ;; + tile*-*) TARGET=TILE; TARGETDIR=tile SOURCES="ffi.c tile.S" diff --git a/libffi/src/sw_64/ffi.c b/libffi/src/sw_64/ffi.c new file mode 100644 index 000000000..2accc48ad --- /dev/null +++ b/libffi/src/sw_64/ffi.c @@ -0,0 +1,516 @@ +/* ----------------------------------------------------------------------- + ffi.c - Copyright (c) 2012 Anthony Green + Copyright (c) 1998, 2001, 2007, 2008 Red Hat, Inc. + Copyright (c) 2023, Wxiat + Sunway 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 +#include +#include +#include "internal.h" + +/* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE; + all further uses in this file will refer to the 128-bit type. */ +#if defined(__LONG_DOUBLE_128__) +#if FFI_TYPE_LONGDOUBLE != 4 +#error FFI_TYPE_LONGDOUBLE out of date +#endif +#else +#undef FFI_TYPE_LONGDOUBLE +#define FFI_TYPE_LONGDOUBLE 4 +#endif + +extern void +ffi_call_sysv (void *stack, void *frame, unsigned flags, void *raddr, + void (*fn) (void), void *closure) FFI_HIDDEN; +extern void +ffi_closure_sysv (void) FFI_HIDDEN; +extern void +ffi_go_closure_sysv (void) FFI_HIDDEN; + +/* Promote a float value to its in-register double representation. + Unlike actually casting to double, this does not trap on NaN. */ +static inline UINT64 +lds (void *ptr) +{ + UINT64 ret; + asm ("flds %0,%1" : "=f"(ret) : "m"(*(UINT32 *) ptr)); + return ret; +} + +/* And the reverse. */ +static inline void +sts (void *ptr, UINT64 val) +{ + asm ("fsts %1,%0" : "=m"(*(UINT32 *) ptr) : "f"(val)); +} + +ffi_status FFI_HIDDEN +ffi_prep_cif_machdep (ffi_cif *cif) +{ + size_t bytes = 0; + int flags, i, avn; + ffi_type *rtype, *itype; + + if (cif->abi != FFI_OSF) + return FFI_BAD_ABI; + + /* Compute the size of the argument area. */ + for (i = 0, avn = cif->nargs; i < avn; i++) + { + itype = cif->arg_types[i]; + switch (itype->type) + { + case FFI_TYPE_INT: + case FFI_TYPE_SINT8: + case FFI_TYPE_UINT8: + case FFI_TYPE_SINT16: + case FFI_TYPE_UINT16: + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + case FFI_TYPE_POINTER: + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + case FFI_TYPE_LONGDOUBLE: + /* All take one 8 byte slot. */ + bytes += 8; + break; + + case FFI_TYPE_VOID: + case FFI_TYPE_STRUCT: + /* Passed by value in N slots. */ + bytes += FFI_ALIGN (itype->size, FFI_SIZEOF_ARG); + break; + + case FFI_TYPE_COMPLEX: + /* _Complex long double passed by reference; others in 2 slots. */ + if (itype->elements[0]->type == FFI_TYPE_LONGDOUBLE) + bytes += 8; + else + bytes += 16; + break; + + default: + abort (); + } + } + + /* Set the return type flag */ + rtype = cif->rtype; + switch (rtype->type) + { + case FFI_TYPE_VOID: + flags = SW_64_FLAGS (SW_64_ST_VOID, SW_64_LD_VOID); + break; + case FFI_TYPE_INT: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT32: + flags = SW_64_FLAGS (SW_64_ST_INT, SW_64_LD_INT32); + break; + case FFI_TYPE_FLOAT: + flags = SW_64_FLAGS (SW_64_ST_FLOAT, SW_64_LD_FLOAT); + break; + case FFI_TYPE_DOUBLE: + flags = SW_64_FLAGS (SW_64_ST_DOUBLE, SW_64_LD_DOUBLE); + break; + case FFI_TYPE_UINT8: + flags = SW_64_FLAGS (SW_64_ST_INT, SW_64_LD_UINT8); + break; + case FFI_TYPE_SINT8: + flags = SW_64_FLAGS (SW_64_ST_INT, SW_64_LD_SINT8); + break; + case FFI_TYPE_UINT16: + flags = SW_64_FLAGS (SW_64_ST_INT, SW_64_LD_UINT16); + break; + case FFI_TYPE_SINT16: + flags = SW_64_FLAGS (SW_64_ST_INT, SW_64_LD_SINT16); + break; + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: + case FFI_TYPE_POINTER: + flags = SW_64_FLAGS (SW_64_ST_INT, SW_64_LD_INT64); + break; + case FFI_TYPE_LONGDOUBLE: + case FFI_TYPE_STRUCT: + /* Passed in memory, with a hidden pointer. */ + flags = SW_64_RET_IN_MEM; + break; + case FFI_TYPE_COMPLEX: + itype = rtype->elements[0]; + switch (itype->type) + { + case FFI_TYPE_FLOAT: + flags = SW_64_FLAGS (SW_64_ST_CPLXF, SW_64_LD_CPLXF); + break; + case FFI_TYPE_DOUBLE: + flags = SW_64_FLAGS (SW_64_ST_CPLXD, SW_64_LD_CPLXD); + break; + default: + if (rtype->size <= 8) + flags = SW_64_FLAGS (SW_64_ST_INT, SW_64_LD_INT64); + else + flags = SW_64_RET_IN_MEM; + break; + } + break; + default: + abort (); + } + cif->flags = flags; + + /* Include the hidden structure pointer in args requirement. */ + if (flags == SW_64_RET_IN_MEM) + bytes += 8; + /* Minimum size is 6 slots, so that ffi_call_sysv can pop them. */ + if (bytes < 6 * 8) + bytes = 6 * 8; + cif->bytes = bytes; + + return FFI_OK; +} + +static unsigned long +extend_basic_type (void *valp, int type, int argn) +{ + switch (type) + { + case FFI_TYPE_SINT8: + return *(SINT8 *) valp; + case FFI_TYPE_UINT8: + return *(UINT8 *) valp; + case FFI_TYPE_SINT16: + return *(SINT16 *) valp; + case FFI_TYPE_UINT16: + return *(UINT16 *) valp; + + case FFI_TYPE_FLOAT: + if (argn < 6) + return lds (valp); + /* FALLTHRU */ + + case FFI_TYPE_INT: + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT32: + /* Note that unsigned 32-bit quantities are sign extended. */ + return *(SINT32 *) valp; + + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + case FFI_TYPE_POINTER: + case FFI_TYPE_DOUBLE: + return *(UINT64 *) valp; + + default: + abort (); + } +} + +static void +ffi_call_int (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue, + void *closure) +{ + unsigned long *argp; + long i, avn, argn, flags = cif->flags; + ffi_type **arg_types; + void *frame; + + /* 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 && flags == SW_64_RET_IN_MEM) + rvalue = alloca (cif->rtype->size); + + /* Allocate the space for the arguments, plus 4 words of temp + space for ffi_call_sysv. */ + argp = frame = alloca (cif->bytes + 4 * FFI_SIZEOF_ARG); + frame += cif->bytes; + + argn = 0; + if (flags == SW_64_RET_IN_MEM) + argp[argn++] = (unsigned long) rvalue; + + avn = cif->nargs; + arg_types = cif->arg_types; + + for (i = 0, avn = cif->nargs; i < avn; i++) + { + ffi_type *ty = arg_types[i]; + void *valp = avalue[i]; + int type = ty->type; + size_t size; + + switch (type) + { + case FFI_TYPE_INT: + case FFI_TYPE_SINT8: + case FFI_TYPE_UINT8: + case FFI_TYPE_SINT16: + case FFI_TYPE_UINT16: + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + case FFI_TYPE_POINTER: + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + argp[argn] = extend_basic_type (valp, type, argn); + argn++; + break; + + case FFI_TYPE_LONGDOUBLE: + by_reference: + /* Note that 128-bit long double is passed by reference. */ + argp[argn++] = (unsigned long) valp; + break; + + case FFI_TYPE_VOID: + case FFI_TYPE_STRUCT: + size = ty->size; + memcpy (argp + argn, valp, size); + argn += FFI_ALIGN (size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; + break; + + case FFI_TYPE_COMPLEX: + type = ty->elements[0]->type; + if (type == FFI_TYPE_LONGDOUBLE) + goto by_reference; + + /* Most complex types passed as two separate arguments. */ + size = ty->elements[0]->size; + argp[argn] = extend_basic_type (valp, type, argn); + argp[argn + 1] = extend_basic_type (valp + size, type, argn + 1); + argn += 2; + break; + + default: + abort (); + } + } + + flags = (flags >> SW_64_ST_SHIFT) & 0xff; + ffi_call_sysv (argp, frame, flags, rvalue, fn, closure); +} + +void +ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue) +{ + ffi_call_int (cif, fn, rvalue, avalue, NULL); +} + +void +ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue, + void *closure) +{ + ffi_call_int (cif, fn, rvalue, avalue, closure); +} + +ffi_status +ffi_prep_closure_loc (ffi_closure *closure, ffi_cif *cif, + void (*fun) (ffi_cif *, void *, void **, void *), + void *user_data, void *codeloc) +{ + unsigned int *tramp; + + if (cif->abi != FFI_OSF) + return FFI_BAD_ABI; + + tramp = (unsigned int *) &closure->tramp[0]; + tramp[0] = 0x43fb0741; /* mov $27,$1 */ + tramp[1] = 0x8f7b0010; /* ldl $27,16($27) */ + tramp[2] = 0x0ffb0000; /* jmp $31,($27),0 */ + tramp[3] = 0x43ff075f; /* nop */ + *(void **) &tramp[4] = ffi_closure_sysv; + + closure->cif = cif; + closure->fun = fun; + closure->user_data = user_data; + + /* Flush the Icache. 0x86 is PAL_imb in Tru64 UNIX . */ + asm volatile ("sys_call 0x86" : : : "memory"); + + return FFI_OK; +} + +ffi_status +ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif, + void (*fun) (ffi_cif *, void *, void **, void *)) +{ + if (cif->abi != FFI_OSF) + return FFI_BAD_ABI; + + closure->tramp = (void *) ffi_go_closure_sysv; + closure->cif = cif; + closure->fun = fun; + + return FFI_OK; +} + +long FFI_HIDDEN +ffi_closure_sysv_inner (ffi_cif *cif, + void (*fun) (ffi_cif *, void *, void **, void *), + void *user_data, void *rvalue, unsigned long *argp) +{ + void **avalue; + ffi_type **arg_types; + long i, avn, argn, flags; + + avalue = alloca (cif->nargs * sizeof (void *)); + flags = cif->flags; + argn = 0; + + /* Copy the caller's structure return address to that the closure + returns the data directly to the caller. */ + if (flags == SW_64_RET_IN_MEM) + { + rvalue = (void *) argp[0]; + argn = 1; + } + + arg_types = cif->arg_types; + + /* Grab the addresses of the arguments from the stack frame. */ + for (i = 0, avn = cif->nargs; i < avn; i++) + { + ffi_type *ty = arg_types[i]; + int type = ty->type; + void *valp = &argp[argn]; + size_t size; + + switch (type) + { + case FFI_TYPE_INT: + case FFI_TYPE_SINT8: + case FFI_TYPE_UINT8: + case FFI_TYPE_SINT16: + case FFI_TYPE_UINT16: + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + case FFI_TYPE_POINTER: + argn += 1; + break; + + case FFI_TYPE_VOID: + case FFI_TYPE_STRUCT: + size = ty->size; + argn += FFI_ALIGN (size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; + break; + + case FFI_TYPE_FLOAT: + /* Floats coming from registers need conversion from double + back to float format. */ + if (argn < 6) + { + valp = &argp[argn - 6]; + sts (valp, argp[argn - 6]); + } + argn += 1; + break; + + case FFI_TYPE_DOUBLE: + if (argn < 6) + valp = &argp[argn - 6]; + argn += 1; + break; + + case FFI_TYPE_LONGDOUBLE: + by_reference: + /* 128-bit long double is passed by reference. */ + valp = (void *) argp[argn]; + argn += 1; + break; + + case FFI_TYPE_COMPLEX: + type = ty->elements[0]->type; + switch (type) + { + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + /* Passed as separate arguments, but they wind up sequential. */ + break; + + case FFI_TYPE_INT: + case FFI_TYPE_SINT8: + case FFI_TYPE_UINT8: + case FFI_TYPE_SINT16: + case FFI_TYPE_UINT16: + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT32: + /* Passed as separate arguments. Disjoint, but there's room + enough in one slot to hold the pair. */ + size = ty->elements[0]->size; + memcpy (valp + size, valp + 8, size); + break; + + case FFI_TYPE_FLOAT: + /* Passed as separate arguments. Disjoint, and each piece + may need conversion back to float. */ + if (argn < 6) + { + valp = &argp[argn - 6]; + sts (valp, argp[argn - 6]); + } + if (argn + 1 < 6) + sts (valp + 4, argp[argn + 1 - 6]); + else + *(UINT32 *) (valp + 4) = argp[argn + 1]; + break; + + case FFI_TYPE_DOUBLE: + /* Passed as separate arguments. Only disjoint if one part + is in fp regs and the other is on the stack. */ + if (argn < 5) + valp = &argp[argn - 6]; + else if (argn == 5) + { + valp = alloca (16); + ((UINT64 *) valp)[0] = argp[5 - 6]; + ((UINT64 *) valp)[1] = argp[6]; + } + break; + + case FFI_TYPE_LONGDOUBLE: + goto by_reference; + + default: + abort (); + } + argn += 2; + break; + + default: + abort (); + } + + avalue[i] = valp; + } + + /* Invoke the closure. */ + fun (cif, rvalue, avalue, user_data); + + /* Tell ffi_closure_sysv how to perform return type promotions. */ + return (flags >> SW_64_LD_SHIFT) & 0xff; +} diff --git a/libffi/src/sw_64/ffitarget.h b/libffi/src/sw_64/ffitarget.h new file mode 100644 index 000000000..4ea1493c5 --- /dev/null +++ b/libffi/src/sw_64/ffitarget.h @@ -0,0 +1,60 @@ +/* -----------------------------------------------------------------*-C-*- + ffitarget.h - Copyright (c) 2012 Anthony Green + Copyright (c) 1996-2003 Red Hat, Inc. + Copyright (c) 2023, Wxiat + Target configuration macros for Sunway. + + 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_OSF, + FFI_LAST_ABI, + FFI_DEFAULT_ABI = FFI_OSF +} ffi_abi; +#endif + +#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION +#define FFI_TARGET_HAS_COMPLEX_TYPE + +/* ---- Definitions for closures ----------------------------------------- */ + +#define FFI_CLOSURES 1 +#define FFI_GO_CLOSURES 1 +#define FFI_TRAMPOLINE_SIZE 24 +#define FFI_NATIVE_RAW_API 0 + +#endif diff --git a/libffi/src/sw_64/internal.h b/libffi/src/sw_64/internal.h new file mode 100644 index 000000000..92ad32179 --- /dev/null +++ b/libffi/src/sw_64/internal.h @@ -0,0 +1,23 @@ +#define SW_64_ST_VOID 0 +#define SW_64_ST_INT 1 +#define SW_64_ST_FLOAT 2 +#define SW_64_ST_DOUBLE 3 +#define SW_64_ST_CPLXF 4 +#define SW_64_ST_CPLXD 5 + +#define SW_64_LD_VOID 0 +#define SW_64_LD_INT64 1 +#define SW_64_LD_INT32 2 +#define SW_64_LD_UINT16 3 +#define SW_64_LD_SINT16 4 +#define SW_64_LD_UINT8 5 +#define SW_64_LD_SINT8 6 +#define SW_64_LD_FLOAT 7 +#define SW_64_LD_DOUBLE 8 +#define SW_64_LD_CPLXF 9 +#define SW_64_LD_CPLXD 10 + +#define SW_64_ST_SHIFT 0 +#define SW_64_LD_SHIFT 8 +#define SW_64_RET_IN_MEM 0x10000 +#define SW_64_FLAGS(S, L) (((L) << SW_64_LD_SHIFT) | (S)) diff --git a/libffi/src/sw_64/sysv.S b/libffi/src/sw_64/sysv.S new file mode 100644 index 000000000..2c31400a4 --- /dev/null +++ b/libffi/src/sw_64/sysv.S @@ -0,0 +1,281 @@ +/* ----------------------------------------------------------------------- + sysv.S - Copyright (c) 1998, 2001, 2007, 2008, 2011, 2014 Red Hat + Copyright (c) 2023, Wxiat + Sunway/SYSV 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 +#include +#include +#include "internal.h" + + .arch sw6a + .text + +/* Aid in building a direct addressed jump table, 4 insns per entry. */ +.macro E index + .align 4 + .org 99b + \index * 16 +.endm + +/* ffi_call_sysv (void *stack, void *frame, unsigned flags, + void *raddr, void (*fnaddr)(void), void *closure) + + Bit o trickiness here -- FRAME is the base of the stack frame + for this function. This has been allocated by ffi_call. We also + deallocate some of the stack that has been alloca'd. */ + + .align 4 + .globl ffi_call_sysv + .ent ffi_call_sysv + FFI_HIDDEN(ffi_call_sysv) + +ffi_call_sysv: + cfi_startproc + cfi_def_cfa($17, 32) + mov $16, $30 + stl $26, 0($17) + stl $15, 8($17) + mov $17, $15 + .prologue 0 + cfi_def_cfa_register($15) + cfi_rel_offset($26, 0) + cfi_rel_offset($15, 8) + + stl $18, 16($17) # save flags into frame + stl $19, 24($17) # save rvalue into frame + mov $20, $27 # fn into place for call + mov $21, $1 # closure into static chain + + # Load up all of the (potential) argument registers. + ldl $16, 0($30) + fldd $f16, 0($30) + fldd $f17, 8($30) + ldl $17, 8($30) + fldd $f18, 16($30) + ldl $18, 16($30) + fldd $f19, 24($30) + ldl $19, 24($30) + fldd $f20, 32($30) + ldl $20, 32($30) + fldd $f21, 40($30) + ldl $21, 40($30) + + # Deallocate the register argument area. + ldi $30, 48($30) + + call $26, ($27), 0 +0: + ldih $29, 0($26) !gpdisp!1 + ldl $2, 24($15) # reload rvalue + ldi $29, 0($29) !gpdisp!1 + ldl $3, 16($15) # reload flags + ldi $1, 99f-0b($26) + ldl $26, 0($15) + ldl $15, 8($15) + cfi_restore($26) + cfi_restore($15) + cfi_def_cfa($sp, 0) + seleq $2, 0, $3 # mash null rvalue to void + addl $3, $3, $3 + s8addl $3, $1, $1 # 99f + stcode * 16 + jmp $31, ($1), $st_int + + .align 4 +99: +E 0 + ret +E 1 +$st_int: + stl $0, 0($2) + ret +E 2 + fsts $f0, 0($2) + ret +E 4 + fstd $f0, 0($2) + ret +E 6 + fsts $f0, 0($2) + fsts $f1, 4($2) + ret +E 10 + fstd $f0, 0($2) + fstd $f1, 8($2) + ret + + cfi_endproc + .end ffi_call_sysv + +/* ffi_closure_sysv(...) + + Receives the closure argument in $1. */ + +#define CLOSURE_FS (16*8) + + .align 4 + .globl ffi_go_closure_sysv + .ent ffi_go_closure_sysv + FFI_HIDDEN(ffi_go_closure_sysv) + +ffi_go_closure_sysv: + cfi_startproc + ldgp $29, 0($27) + subl $30, CLOSURE_FS, $30 + cfi_adjust_cfa_offset(CLOSURE_FS) + stl $26, 0($30) + .prologue 1 + cfi_rel_offset($26, 0) + + stl $16, 10*8($30) + stl $17, 11*8($30) + stl $18, 12*8($30) + + ldl $16, 8($1) # load cif + ldl $17, 16($1) # load fun + mov $1, $18 # closure is user_data + br $do_closure + + cfi_endproc + .end ffi_go_closure_sysv + + .align 4 + .globl ffi_closure_sysv + .ent ffi_closure_sysv + FFI_HIDDEN(ffi_closure_sysv) + +ffi_closure_sysv: + cfi_startproc + ldgp $29, 0($27) + subl $30, CLOSURE_FS, $30 + cfi_adjust_cfa_offset(CLOSURE_FS) + stl $26, 0($30) + .prologue 1 + cfi_rel_offset($26, 0) + + # Store all of the potential argument registers in va_list format. + stl $16, 10*8($30) + stl $17, 11*8($30) + stl $18, 12*8($30) + + ldl $16, 24($1) # load cif + ldl $17, 32($1) # load fun + ldl $18, 40($1) # load user_data + +$do_closure: + stl $19, 13*8($30) + stl $20, 14*8($30) + stl $21, 15*8($30) + fstd $f16, 4*8($30) + fstd $f17, 5*8($30) + fstd $f18, 6*8($30) + fstd $f19, 7*8($30) + fstd $f20, 8*8($30) + fstd $f21, 9*8($30) + + # Call ffi_closure_sysv_inner to do the bulk of the work. + ldi $19, 2*8($30) + ldi $20, 10*8($30) + call $26, ffi_closure_sysv_inner +0: + ldih $29, 0($26) !gpdisp!2 + ldi $2, 99f-0b($26) + s4addl $0, 0, $1 # ldcode * 4 + ldl $0, 16($30) # preload return value + s4addl $1, $2, $1 # 99f + ldcode * 16 + ldi $29, 0($29) !gpdisp!2 + ldl $26, 0($30) + cfi_restore($26) + jmp $31, ($1), $load_32 + +.macro epilogue + addl $30, CLOSURE_FS, $30 + cfi_adjust_cfa_offset(-CLOSURE_FS) + ret + .align 4 + cfi_adjust_cfa_offset(CLOSURE_FS) +.endm + + .align 4 +99: +E 0 + epilogue + +E 1 + epilogue + +E 2 +$load_32: + sextl $0, $0 + epilogue + +E 3 + zapnot $0, 3, $0 + epilogue + +E 4 +#ifdef __sw_64_bwx__ + sexth $0, $0 +#else + sll $0, 48, $0 + sra $0, 48, $0 +#endif + epilogue + +E 5 + and $0, 0xff, $0 + epilogue + +E 6 +#ifdef __sw_64_bwx__ + sextb $0, $0 +#else + sll $0, 56, $0 + sra $0, 56, $0 +#endif + epilogue + +E 7 + flds $f0, 16($sp) + epilogue + +E 8 + fldd $f0, 16($sp) + epilogue + +E 9 + flds $f0, 16($sp) + flds $f1, 20($sp) + epilogue + +E 10 + fldd $f0, 16($sp) + fldd $f1, 24($sp) + epilogue + + cfi_endproc + .end ffi_closure_sysv + +#if defined __ELF__ && defined __linux__ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/libffi/src/types.c b/libffi/src/types.c index 9ec27f6cf..6a31d380e 100644 --- a/libffi/src/types.c +++ b/libffi/src/types.c @@ -80,13 +80,13 @@ FFI_TYPEDEF(pointer, void*, FFI_TYPE_POINTER, const); FFI_TYPEDEF(float, float, FFI_TYPE_FLOAT, const); FFI_TYPEDEF(double, double, FFI_TYPE_DOUBLE, const); -#if !defined HAVE_LONG_DOUBLE_VARIANT || defined __alpha__ +#if !defined HAVE_LONG_DOUBLE_VARIANT || defined __alpha__ || defined __sw_64__ #define FFI_LDBL_CONST const #else #define FFI_LDBL_CONST #endif -#ifdef __alpha__ +#ifdef __alpha__ || defined __sw_64__ /* Even if we're not configured to default to 128-bit long double, maintain binary compatibility, as -mlong-double-128 can be used at any time. */ -- 2.25.1