From 399558e5a99db58839e2a9a8802f743d9631466a Mon Sep 17 00:00:00 2001 From: wuzx Date: Fri, 18 Nov 2022 12:04:50 +0800 Subject: [PATCH] Add sw64 architecture Add sw64 architecture in file Makefile.am Makefile.in config.guess config.sub configure configure.host m4/ax_gcc_archflag.m4 src/sw_64/ffi.c src/sw_64/ffitarget.h src/sw_64/internal.h src/sw_64/osf.S src/types.c and testsuite/libffi.go/static-chain.h to support sw64 architecture. Signed-off-by: wuzx --- Makefile.am | 2 + Makefile.in | 24 ++ config.guess | 9 + config.sub | 1 + configure | 2 +- configure.host | 6 + m4/ax_gcc_archflag.m4 | 2 +- src/sw_64/ffi.c | 521 +++++++++++++++++++++++++++++ src/sw_64/ffitarget.h | 57 ++++ src/sw_64/internal.h | 23 ++ src/sw_64/osf.S | 282 ++++++++++++++++ src/types.c | 4 +- testsuite/libffi.go/static-chain.h | 2 + 13 files changed, 931 insertions(+), 4 deletions(-) create mode 100644 src/sw_64/ffi.c create mode 100644 src/sw_64/ffitarget.h create mode 100644 src/sw_64/internal.h create mode 100644 src/sw_64/osf.S diff --git a/Makefile.am b/Makefile.am index 1b18198..e29722f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -47,6 +47,7 @@ endif noinst_HEADERS = src/aarch64/ffitarget.h src/aarch64/internal.h \ src/alpha/ffitarget.h src/alpha/internal.h \ + src/sw_64/ffitarget.h src/sw_64/internal.h \ src/arc/ffitarget.h src/arm/ffitarget.h src/arm/internal.h \ src/avr32/ffitarget.h src/bfin/ffitarget.h \ src/cris/ffitarget.h src/csky/ffitarget.h src/frv/ffitarget.h \ @@ -67,6 +68,7 @@ noinst_HEADERS = src/aarch64/ffitarget.h src/aarch64/internal.h \ EXTRA_libffi_la_SOURCES = src/aarch64/ffi.c src/aarch64/sysv.S \ src/aarch64/win64_armasm.S src/alpha/ffi.c src/alpha/osf.S \ + src/sw_64/ffi.c src/sw_64/osf.S src/arc/ffi.c src/arc/arcompact.S src/arm/ffi.c \ src/arm/sysv.S src/arm/ffi.c src/arm/sysv_msvc_arm32.S \ src/avr32/ffi.c src/avr32/sysv.S src/bfin/ffi.c \ diff --git a/Makefile.in b/Makefile.in index a4b67a7..b4eddc2 100644 --- a/Makefile.in +++ b/Makefile.in @@ -202,6 +202,7 @@ am__depfiles_remade = src/$(DEPDIR)/closures.Plo \ src/aarch64/$(DEPDIR)/ffi.Plo src/aarch64/$(DEPDIR)/sysv.Plo \ src/aarch64/$(DEPDIR)/win64_armasm.Plo \ src/alpha/$(DEPDIR)/ffi.Plo src/alpha/$(DEPDIR)/osf.Plo \ + src/sw_64/$(DEPDIR)/ffi.Plo src/sw_64/$(DEPDIR)/osf.Plo \ src/arc/$(DEPDIR)/arcompact.Plo src/arc/$(DEPDIR)/ffi.Plo \ src/arm/$(DEPDIR)/ffi.Plo src/arm/$(DEPDIR)/sysv.Plo \ src/arm/$(DEPDIR)/sysv_msvc_arm32.Plo \ @@ -548,6 +549,7 @@ libffi_la_SOURCES = src/prep_cif.c src/types.c src/raw_api.c \ src/java_raw_api.c src/closures.c src/tramp.c $(am__append_2) noinst_HEADERS = src/aarch64/ffitarget.h src/aarch64/internal.h \ src/alpha/ffitarget.h src/alpha/internal.h \ + src/sw_64/ffitarget.h src/sw_64/internal.h \ src/arc/ffitarget.h src/arm/ffitarget.h src/arm/internal.h \ src/avr32/ffitarget.h src/bfin/ffitarget.h \ src/cris/ffitarget.h src/csky/ffitarget.h src/frv/ffitarget.h \ @@ -568,6 +570,7 @@ noinst_HEADERS = src/aarch64/ffitarget.h src/aarch64/internal.h \ EXTRA_libffi_la_SOURCES = src/aarch64/ffi.c src/aarch64/sysv.S \ src/aarch64/win64_armasm.S src/alpha/ffi.c src/alpha/osf.S \ + src/sw_64/ffi.c src/sw_64/osf.S \ src/arc/ffi.c src/arc/arcompact.S src/arm/ffi.c \ src/arm/sysv.S src/arm/ffi.c src/arm/sysv_msvc_arm32.S \ src/avr32/ffi.c src/avr32/sysv.S src/bfin/ffi.c \ @@ -751,6 +754,16 @@ src/alpha/ffi.lo: src/alpha/$(am__dirstamp) \ src/alpha/$(DEPDIR)/$(am__dirstamp) src/alpha/osf.lo: src/alpha/$(am__dirstamp) \ src/alpha/$(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/osf.lo: src/sw_64/$(am__dirstamp) \ + src/sw_64/$(DEPDIR)/$(am__dirstamp) src/arc/$(am__dirstamp): @$(MKDIR_P) src/arc @: > src/arc/$(am__dirstamp) @@ -1096,6 +1109,8 @@ mostlyclean-compile: -rm -f src/aarch64/*.lo -rm -f src/alpha/*.$(OBJEXT) -rm -f src/alpha/*.lo + -rm -f src/sw_64/*.$(OBJEXT) + -rm -f src/sw_64/*.lo -rm -f src/arc/*.$(OBJEXT) -rm -f src/arc/*.lo -rm -f src/arm/*.$(OBJEXT) @@ -1168,6 +1183,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/aarch64/$(DEPDIR)/ffi.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/aarch64/$(DEPDIR)/sysv.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/aarch64/$(DEPDIR)/win64_armasm.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/sw_64/$(DEPDIR)/ffi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/sw_64/$(DEPDIR)/osf.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/alpha/$(DEPDIR)/ffi.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/alpha/$(DEPDIR)/osf.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/arc/$(DEPDIR)/arcompact.Plo@am__quote@ # am--include-marker @@ -1311,6 +1328,7 @@ clean-libtool: -rm -rf .libs _libs -rm -rf src/.libs src/_libs -rm -rf src/aarch64/.libs src/aarch64/_libs + -rm -rf src/sw_64/.libs src/sw_64/_libs -rm -rf src/alpha/.libs src/alpha/_libs -rm -rf src/arc/.libs src/arc/_libs -rm -rf src/arm/.libs src/arm/_libs @@ -1710,6 +1728,8 @@ distclean-generic: -rm -f src/$(am__dirstamp) -rm -f src/aarch64/$(DEPDIR)/$(am__dirstamp) -rm -f src/aarch64/$(am__dirstamp) + -rm -f src/sw_64/$(DEPDIR)/$(am__dirstamp) + -rm -f src/sw_64/$(am__dirstamp) -rm -f src/alpha/$(DEPDIR)/$(am__dirstamp) -rm -f src/alpha/$(am__dirstamp) -rm -f src/arc/$(DEPDIR)/$(am__dirstamp) @@ -1792,6 +1812,8 @@ distclean: distclean-recursive -rm -f src/aarch64/$(DEPDIR)/ffi.Plo -rm -f src/aarch64/$(DEPDIR)/sysv.Plo -rm -f src/aarch64/$(DEPDIR)/win64_armasm.Plo + -rm -f src/sw_64/$(DEPDIR)/ffi.Plo + -rm -f src/sw_64/$(DEPDIR)/osf.Plo -rm -f src/alpha/$(DEPDIR)/ffi.Plo -rm -f src/alpha/$(DEPDIR)/osf.Plo -rm -f src/arc/$(DEPDIR)/arcompact.Plo @@ -1930,6 +1952,8 @@ maintainer-clean: maintainer-clean-recursive -rm -f src/aarch64/$(DEPDIR)/ffi.Plo -rm -f src/aarch64/$(DEPDIR)/sysv.Plo -rm -f src/aarch64/$(DEPDIR)/win64_armasm.Plo + -rm -f src/sw_64/$(DEPDIR)/ffi.Plo + -rm -f src/sw_64/$(DEPDIR)/osf.Plo -rm -f src/alpha/$(DEPDIR)/ffi.Plo -rm -f src/alpha/$(DEPDIR)/osf.Plo -rm -f src/arc/$(DEPDIR)/arcompact.Plo diff --git a/config.guess b/config.guess index e94095c..01a1ef3 100644 --- a/config.guess +++ b/config.guess @@ -925,6 +925,15 @@ EOF UNAME_MACHINE=aarch64_be echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; + sw_64:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + sw) UNAME_MACHINE=sw_64 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + echo ${UNAME_MACHINE}-sunway-linux-${LIBC} + exit ;; + alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in EV5) UNAME_MACHINE=alphaev5 ;; diff --git a/config.sub b/config.sub index 14b5150..bbb4efe 100644 --- a/config.sub +++ b/config.sub @@ -1158,6 +1158,7 @@ case $cpu-$vendor in case $cpu in 1750a | 580 \ | a29k \ + | sw_64 \ | aarch64 | aarch64_be \ | abacus \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \ diff --git a/configure b/configure index 94e149c..f911a05 100755 --- a/configure +++ b/configure @@ -17216,7 +17216,7 @@ fi *hypersparc*|*rt62[056]*) ax_gcc_arch="hypersparc v8" ;; *cypress*) ax_gcc_arch=cypress ;; esac ;; - + sw_64*) ax_gcc_arch=sw6b ;; alphaev5) ax_gcc_arch=ev5 ;; alphaev56) ax_gcc_arch=ev56 ;; alphapca56) ax_gcc_arch="pca56 ev56" ;; diff --git a/configure.host b/configure.host index 2682671..372e20b 100644 --- a/configure.host +++ b/configure.host @@ -24,6 +24,12 @@ case "${host}" in HAVE_LONG_DOUBLE='defined(__LONG_DOUBLE_128__)' SOURCES="ffi.c osf.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 osf.S" + ;; arc*-*-*) TARGET=ARC; TARGETDIR=arc diff --git a/m4/ax_gcc_archflag.m4 b/m4/ax_gcc_archflag.m4 index c52b9b2..de17232 100644 --- a/m4/ax_gcc_archflag.m4 +++ b/m4/ax_gcc_archflag.m4 @@ -174,7 +174,7 @@ case $host_cpu in *hypersparc*|*rt62[[056]]*) ax_gcc_arch="hypersparc v8" ;; *cypress*) ax_gcc_arch=cypress ;; esac ;; - + sw_64*) ax_gcc_arch=sw6b ;; alphaev5) ax_gcc_arch=ev5 ;; alphaev56) ax_gcc_arch=ev56 ;; alphapca56) ax_gcc_arch="pca56 ev56" ;; diff --git a/src/sw_64/ffi.c b/src/sw_64/ffi.c new file mode 100644 index 0000000..d99668f --- /dev/null +++ b/src/sw_64/ffi.c @@ -0,0 +1,521 @@ +/* ----------------------------------------------------------------------- + ffi.c - Copyright (c) 2012 Anthony Green + Copyright (c) 1998, 2001, 2007, 2008 Red Hat, Inc. + + Alpha 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_osf(void *stack, void *frame, unsigned flags, + void *raddr, void (*fn)(void), void *closure) + FFI_HIDDEN; +extern void ffi_closure_osf(void) FFI_HIDDEN; +extern void ffi_go_closure_osf(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_osf 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_osf. */ + 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_osf(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; /* ldq $27,16($27) */ + tramp[2] = 0x0ffb0000; /* jmp $31,($27),0 */ + tramp[3] = 0x43ff075f; /* nop */ + *(void **) &tramp[4] = ffi_closure_osf; + + closure->cif = cif; + closure->fun = fun; + closure->user_data = user_data; + + /* Flush the Icache. + + Tru64 UNIX as doesn't understand the imb mnemonic, so use call_pal + instead, since both Compaq as and gas can handle it. + + 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_osf; + closure->cif = cif; + closure->fun = fun; + + return FFI_OK; +} + +long FFI_HIDDEN +ffi_closure_osf_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_osf how to perform return type promotions. */ + return (flags >> SW_64_LD_SHIFT) & 0xff; +} diff --git a/src/sw_64/ffitarget.h b/src/sw_64/ffitarget.h new file mode 100644 index 0000000..a02dbd0 --- /dev/null +++ b/src/sw_64/ffitarget.h @@ -0,0 +1,57 @@ +/* -----------------------------------------------------------------*-C-*- + ffitarget.h - Copyright (c) 2012 Anthony Green + Copyright (c) 1996-2003 Red Hat, Inc. + Target configuration macros for Alpha. + + 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/src/sw_64/internal.h b/src/sw_64/internal.h new file mode 100644 index 0000000..1866a8c --- /dev/null +++ b/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/src/sw_64/osf.S b/src/sw_64/osf.S new file mode 100644 index 0000000..b4b58e5 --- /dev/null +++ b/src/sw_64/osf.S @@ -0,0 +1,282 @@ +/* ----------------------------------------------------------------------- + osf.S - Copyright (c) 1998, 2001, 2007, 2008, 2011, 2014 Red Hat + + SW_64/OSF 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 sw6b + .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_osf (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_osf + .ent ffi_call_osf + FFI_HIDDEN(ffi_call_osf) + +ffi_call_osf: + 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, SW_64_ST_VOID, $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 SW_64_ST_VOID + ret +E SW_64_ST_INT +$st_int: + stl $0, 0($2) + ret +E SW_64_ST_FLOAT + fsts $f0, 0($2) + ret +E SW_64_ST_DOUBLE + fstd $f0, 0($2) + ret +E SW_64_ST_CPLXF + fsts $f0, 0($2) + fsts $f1, 4($2) + ret +E SW_64_ST_CPLXD + fstd $f0, 0($2) + fstd $f1, 8($2) + ret + + cfi_endproc + .end ffi_call_osf + +/* ffi_closure_osf(...) + + Receives the closure argument in $1. */ + +#define CLOSURE_FS (16*8) + + .align 4 + .globl ffi_go_closure_osf + .ent ffi_go_closure_osf + FFI_HIDDEN(ffi_go_closure_osf) + +ffi_go_closure_osf: + 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_osf + + .align 4 + .globl ffi_closure_osf + .ent ffi_closure_osf + FFI_HIDDEN(ffi_closure_osf) + +ffi_closure_osf: + 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_osf_inner to do the bulk of the work. + ldi $19, 2*8($30) + ldi $20, 10*8($30) + call $26, ffi_closure_osf_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 SW_64_LD_VOID + epilogue + +E SW_64_LD_INT64 + epilogue + +E SW_64_LD_INT32 +$load_32: + sextl $0, $0 + epilogue + +E SW_64_LD_UINT16 + zapnot $0, 3, $0 + epilogue + +E SW_64_LD_SINT16 +#ifdef __sw_64_bwx__ + sexth $0, $0 +#else + sll $0, 48, $0 + sra $0, 48, $0 +#endif + epilogue + +E SW_64_LD_UINT8 + and $0, 0xff, $0 + epilogue + +E SW_64_LD_SINT8 +#ifdef __sw_64_bwx__ + sextb $0, $0 +#else + sll $0, 56, $0 + sra $0, 56, $0 +#endif + epilogue + +E SW_64_LD_FLOAT + flds $f0, 16($sp) + epilogue + +E SW_64_LD_DOUBLE + fldd $f0, 16($sp) + epilogue + +E SW_64_LD_CPLXF + flds $f0, 16($sp) + flds $f1, 20($sp) + epilogue + +E SW_64_LD_CPLXD + fldd $f0, 16($sp) + fldd $f1, 24($sp) + epilogue + + cfi_endproc + .end ffi_closure_osf + +#if defined __ELF__ && defined __linux__ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/src/types.c b/src/types.c index 9ec27f6..e5f666b 100644 --- a/src/types.c +++ b/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__ +#if defined __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. */ diff --git a/testsuite/libffi.go/static-chain.h b/testsuite/libffi.go/static-chain.h index 3675b40..25ef76e 100644 --- a/testsuite/libffi.go/static-chain.h +++ b/testsuite/libffi.go/static-chain.h @@ -2,6 +2,8 @@ # define STATIC_CHAIN_REG "x18" #elif defined(__alpha__) # define STATIC_CHAIN_REG "$1" +#elif defined(__sw_64__) +# define STATIC_CHAIN_REG "$1" #elif defined(__arm__) # define STATIC_CHAIN_REG "ip" #elif defined(__sparc__) -- 2.33.0