From 9d5ee5ee619041f7910c6bb3471f94042f787fc4 Mon Sep 17 00:00:00 2001 From: Hailiang Date: Fri, 28 Feb 2025 18:16:16 +0800 Subject: [PATCH 1/3] add sw_64 support --- libffi-Add-sw64-architecture.patch | 1012 ++++++++++++++++++++++++++++ libffi.spec | 7 +- 2 files changed, 1018 insertions(+), 1 deletion(-) create mode 100644 libffi-Add-sw64-architecture.patch diff --git a/libffi-Add-sw64-architecture.patch b/libffi-Add-sw64-architecture.patch new file mode 100644 index 0000000..0456bdd --- /dev/null +++ b/libffi-Add-sw64-architecture.patch @@ -0,0 +1,1012 @@ +Description: Add support for sunway +Author: Miao Changwei +Last-Update: 2022-04-07 + +--- + Makefile.am | 2 + + config.guess | 4 + + config.sub | 2 +- + configure.host | 7 + + src/sw64/ffi.c | 517 ++++++++++++++++++ + src/sw64/ffitarget.h | 58 ++ + src/sw64/internal.h | 23 + + src/sw64/sysv.S | 283 ++++++++++ + .../libffi.complex/cls_complex_va_float.c | 4 +- + 9 files changed, 897 insertions(+), 3 deletions(-) + create mode 100644 src/sw64/ffi.c + create mode 100644 src/sw64/ffitarget.h + create mode 100644 src/sw64/internal.h + create mode 100644 src/sw64/sysv.S + +diff --git a/Makefile.am b/Makefile.am +index a4a4887..747d129 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -62,6 +62,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/sw64/ffitarget.h src/sw64/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 src/kvx/asm.h \ +@@ -91,6 +92,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/sw64/ffi.c src/sw64/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 \ +diff --git a/config.guess b/config.guess +index 7f76b62..fe6f8bc 100644 +--- a/config.guess ++++ b/config.guess +@@ -990,6 +990,10 @@ EOF + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; ++ sw_64:Linux:*:* | sw64:Linux:*:*) ++ UNAME_MACHINE=sw_64 ++ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" ++ exit ;; + arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; +diff --git a/config.sub b/config.sub +index dba16e8..c0d9565 100644 +--- a/config.sub ++++ b/config.sub +@@ -1266,7 +1266,7 @@ case $cpu-$vendor in + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \ + | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \ +- | spu \ ++ | spu | sw_64 \ + | tahoe \ + | thumbv7* \ + | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \ +diff --git a/configure.host b/configure.host +index f23716f..0304d5a 100644 +--- a/configure.host ++++ b/configure.host +@@ -254,6 +254,13 @@ case "${host}" in + SOURCES="ffi.c ffi64.c v8.S v9.S" + ;; + ++ sw_64*-*-* | sw64*-*-*) ++ TARGET=SW64; TARGETDIR=sw64; ++ # 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/src/sw64/ffi.c b/src/sw64/ffi.c +new file mode 100644 +index 0000000..5c26580 +--- /dev/null ++++ b/src/sw64/ffi.c +@@ -0,0 +1,517 @@ ++/* ----------------------------------------------------------------------- ++ ffi.c - Copyright (c) 2012 Anthony Green ++ Copyright (c) 1998, 2001, 2007, 2008 Red Hat, Inc. ++ Copyright (c) 2021, UnionTech Software Technology Co., Ltd. ++ ++ 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_SYSV) ++ 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 = SW64_FLAGS(SW64_ST_VOID, SW64_LD_VOID); ++ break; ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ flags = SW64_FLAGS(SW64_ST_INT, SW64_LD_INT32); ++ break; ++ case FFI_TYPE_FLOAT: ++ flags = SW64_FLAGS(SW64_ST_FLOAT, SW64_LD_FLOAT); ++ break; ++ case FFI_TYPE_DOUBLE: ++ flags = SW64_FLAGS(SW64_ST_DOUBLE, SW64_LD_DOUBLE); ++ break; ++ case FFI_TYPE_UINT8: ++ flags = SW64_FLAGS(SW64_ST_INT, SW64_LD_UINT8); ++ break; ++ case FFI_TYPE_SINT8: ++ flags = SW64_FLAGS(SW64_ST_INT, SW64_LD_SINT8); ++ break; ++ case FFI_TYPE_UINT16: ++ flags = SW64_FLAGS(SW64_ST_INT, SW64_LD_UINT16); ++ break; ++ case FFI_TYPE_SINT16: ++ flags = SW64_FLAGS(SW64_ST_INT, SW64_LD_SINT16); ++ break; ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_POINTER: ++ flags = SW64_FLAGS(SW64_ST_INT, SW64_LD_INT64); ++ break; ++ case FFI_TYPE_LONGDOUBLE: ++ case FFI_TYPE_STRUCT: ++ /* Passed in memory, with a hidden pointer. */ ++ flags = SW64_RET_IN_MEM; ++ break; ++ case FFI_TYPE_COMPLEX: ++ itype = rtype->elements[0]; ++ switch (itype->type) ++ { ++ case FFI_TYPE_FLOAT: ++ flags = SW64_FLAGS(SW64_ST_CPLXF, SW64_LD_CPLXF); ++ break; ++ case FFI_TYPE_DOUBLE: ++ flags = SW64_FLAGS(SW64_ST_CPLXD, SW64_LD_CPLXD); ++ break; ++ default: ++ if (rtype->size <= 8) ++ flags = SW64_FLAGS(SW64_ST_INT, SW64_LD_INT64); ++ else ++ flags = SW64_RET_IN_MEM; ++ break; ++ } ++ break; ++ default: ++ abort(); ++ } ++ cif->flags = flags; ++ ++ /* Include the hidden structure pointer in args requirement. */ ++ if (flags == SW64_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 == SW64_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 == SW64_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 >> SW64_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_SYSV) ++ 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 HMC_imb . */ ++ 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_SYSV) ++ 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 == SW64_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 >> SW64_LD_SHIFT) & 0xff; ++} +diff --git a/src/sw64/ffitarget.h b/src/sw64/ffitarget.h +new file mode 100644 +index 0000000..ae50a54 +--- /dev/null ++++ b/src/sw64/ffitarget.h +@@ -0,0 +1,58 @@ ++/* -----------------------------------------------------------------*-C-*- ++ ffitarget.h - Copyright (c) 2012 Anthony Green ++ Copyright (c) 1996-2003 Red Hat, Inc. ++ Copyright (c) 2021 UnionTech Software Technology Co., Ltd. ++ 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_SYSV, ++ FFI_LAST_ABI, ++ FFI_DEFAULT_ABI = FFI_SYSV ++} 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/sw64/internal.h b/src/sw64/internal.h +new file mode 100644 +index 0000000..7a7492b +--- /dev/null ++++ b/src/sw64/internal.h +@@ -0,0 +1,23 @@ ++#define SW64_ST_VOID 0 ++#define SW64_ST_INT 1 ++#define SW64_ST_FLOAT 2 ++#define SW64_ST_DOUBLE 3 ++#define SW64_ST_CPLXF 4 ++#define SW64_ST_CPLXD 5 ++ ++#define SW64_LD_VOID 0 ++#define SW64_LD_INT64 1 ++#define SW64_LD_INT32 2 ++#define SW64_LD_UINT16 3 ++#define SW64_LD_SINT16 4 ++#define SW64_LD_UINT8 5 ++#define SW64_LD_SINT8 6 ++#define SW64_LD_FLOAT 7 ++#define SW64_LD_DOUBLE 8 ++#define SW64_LD_CPLXF 9 ++#define SW64_LD_CPLXD 10 ++ ++#define SW64_ST_SHIFT 0 ++#define SW64_LD_SHIFT 8 ++#define SW64_RET_IN_MEM 0x10000 ++#define SW64_FLAGS(S, L) (((L) << SW64_LD_SHIFT) | (S)) +diff --git a/src/sw64/sysv.S b/src/sw64/sysv.S +new file mode 100644 +index 0000000..4568584 +--- /dev/null ++++ b/src/sw64/sysv.S +@@ -0,0 +1,283 @@ ++/* ----------------------------------------------------------------------- ++ sysv.S - Copyright (c) 1998, 2001, 2007, 2008, 2011, 2014 Red Hat ++ Copyright (c) 2021, UnionTech Software Technology Co., Ltd. ++ ++ 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 sw6 ++ .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, SW64_ST_VOID, $3, $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 SW64_ST_VOID ++ ret ++E SW64_ST_INT ++$st_int: ++ stl $0, 0($2) ++ ret ++E SW64_ST_FLOAT ++ fsts $f0, 0($2) ++ ret ++E SW64_ST_DOUBLE ++ fstd $f0, 0($2) ++ ret ++E SW64_ST_CPLXF ++ fsts $f0, 0($2) ++ fsts $f1, 4($2) ++ ret ++E SW64_ST_CPLXD ++ 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 SW64_LD_VOID ++ epilogue ++ ++E SW64_LD_INT64 ++ epilogue ++ ++E SW64_LD_INT32 ++$load_32: ++ sextl $0, $0 ++ epilogue ++ ++E SW64_LD_UINT16 ++ zapnot $0, 3, $0 ++ epilogue ++ ++E SW64_LD_SINT16 ++#ifdef __sw_64_bwx__ ++ sexth $0, $0 ++#else ++ sll $0, 48, $0 ++ sra $0, 48, $0 ++#endif ++ epilogue ++ ++E SW64_LD_UINT8 ++ and $0, 0xff, $0 ++ epilogue ++ ++E SW64_LD_SINT8 ++#ifdef __sw_64_bwx__ ++ sextb $0, $0 ++#else ++ sll $0, 56, $0 ++ sra $0, 56, $0 ++#endif ++ epilogue ++ ++E SW64_LD_FLOAT ++ flds $f0, 16($sp) ++ epilogue ++ ++E SW64_LD_DOUBLE ++ fldd $f0, 16($sp) ++ epilogue ++ ++E SW64_LD_CPLXF ++ flds $f0, 16($sp) ++ flds $f1, 20($sp) ++ epilogue ++ ++E SW64_LD_CPLXD ++ fldd $f0, 16($sp) ++ fldd $f1, 24($sp) ++ epilogue ++ ++ cfi_endproc ++ .end ffi_closure_SYSV ++ ++#if defined __SYSV__ && defined __linux__ ++ .section .note.GNU-stack,"",@progbits ++#endif +diff --git a/testsuite/libffi.complex/cls_complex_va_float.c b/testsuite/libffi.complex/cls_complex_va_float.c +index 2b17826..0861ac6 100644 +--- a/testsuite/libffi.complex/cls_complex_va_float.c ++++ b/testsuite/libffi.complex/cls_complex_va_float.c +@@ -6,11 +6,11 @@ + + /* { dg-do run } */ + +-/* Alpha splits _Complex into two arguments. It's illegal to pass ++/* Alpha/Sunway splits _Complex into two arguments. It's illegal to pass + float through varargs, so _Complex float goes badly. In sort of + gets passed as _Complex double, but the compiler doesn't agree + with itself on this issue. */ +-/* { dg-do run { xfail alpha*-*-* } } */ ++/* { dg-do run { xfail alpha*-*-* sw64*-*-* sw_64*-*-* } } */ + + #include "complex_defs_float.inc" + #include "cls_complex_va.inc" +-- +2.31.1 + diff --git a/libffi.spec b/libffi.spec index cbc288d..ac57bde 100644 --- a/libffi.spec +++ b/libffi.spec @@ -1,6 +1,6 @@ Name: libffi Version: 3.4.4 -Release: 3 +Release: 4 Summary: A Portable Foreign Function Interface Library License: MIT URL: http://sourceware.org/libffi @@ -10,6 +10,7 @@ Source2: ffitarget-multilib.h Patch0: backport-Fix-signed-vs-unsigned-comparison.patch Patch1: fix-AARCH64EB-support.patch +Patch2: libffi-Add-sw64-architecture.patch BuildRequires: gcc gcc-c++ dejagnu BuildRequires: make @@ -56,6 +57,7 @@ The help package contains man files. %setup -q %patch0 -p1 %patch1 -p1 +%patch2 -p1 %build %configure \ @@ -99,6 +101,9 @@ fi %{_infodir}/libffi.info.gz %changelog +* Fri Feb 28 2025 mahailiang - 3.4.4-4 +- add sw_64 support + * Thu May 25 2023 shixin - 3.4.4-3 - Type:bugfix - ID:NA -- Gitee From f6c130c4823e36058c454af2a21c78eb82248f91 Mon Sep 17 00:00:00 2001 From: Hailiang Date: Mon, 3 Mar 2025 18:17:07 +0800 Subject: [PATCH 2/3] add sw_64 support --- 0001-test1.patch | 35 ++++++++++++++++++++++++++++++ libffi-Add-sw64-architecture.patch | 29 +++++++++++++++---------- 2 files changed, 52 insertions(+), 12 deletions(-) create mode 100644 0001-test1.patch diff --git a/0001-test1.patch b/0001-test1.patch new file mode 100644 index 0000000..83b84aa --- /dev/null +++ b/0001-test1.patch @@ -0,0 +1,35 @@ +From 0eb582c348755f9b8f527c066535f95b10deddbf Mon Sep 17 00:00:00 2001 +From: Hailiang +Date: Mon, 3 Mar 2025 18:12:21 +0800 +Subject: [PATCH] test1 + +--- + config.guess | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/config.guess b/config.guess +index fe6f8bc..1239812 100644 +--- a/config.guess ++++ b/config.guess +@@ -990,10 +990,14 @@ EOF + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; +- sw_64:Linux:*:* | sw64:Linux:*:*) +- UNAME_MACHINE=sw_64 +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" +- exit ;; ++ sw_64:Linux:*:*) ++ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in ++ sw) UNAME_MACHINE=sw_64 ;; ++ esac ++ objdump --private-headers /bin/sh | grep -q ld.so.1 ++ if test "$?" = 0 ; then LIBC=gnulibc1 ; fi ++ GUESS=$UNAME_MACHINE-sunway-linux-$LIBC ++ ;; + arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; +-- +2.20.1 + diff --git a/libffi-Add-sw64-architecture.patch b/libffi-Add-sw64-architecture.patch index 0456bdd..c33ad2f 100644 --- a/libffi-Add-sw64-architecture.patch +++ b/libffi-Add-sw64-architecture.patch @@ -1,10 +1,11 @@ -Description: Add support for sunway -Author: Miao Changwei -Last-Update: 2022-04-07 +From 54fd7709a7985d7b93cf2de11415ca3e1f7a55ce Mon Sep 17 00:00:00 2001 +From: Hailiang +Date: Mon, 3 Mar 2025 18:14:32 +0800 +Subject: [PATCH] libffi Add sw64 architecture --- Makefile.am | 2 + - config.guess | 4 + + config.guess | 8 + config.sub | 2 +- configure.host | 7 + src/sw64/ffi.c | 517 ++++++++++++++++++ @@ -12,7 +13,7 @@ Last-Update: 2022-04-07 src/sw64/internal.h | 23 + src/sw64/sysv.S | 283 ++++++++++ .../libffi.complex/cls_complex_va_float.c | 4 +- - 9 files changed, 897 insertions(+), 3 deletions(-) + 9 files changed, 901 insertions(+), 3 deletions(-) create mode 100644 src/sw64/ffi.c create mode 100644 src/sw64/ffitarget.h create mode 100644 src/sw64/internal.h @@ -39,17 +40,21 @@ index a4a4887..747d129 100644 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 \ diff --git a/config.guess b/config.guess -index 7f76b62..fe6f8bc 100644 +index 7f76b62..1239812 100644 --- a/config.guess +++ b/config.guess -@@ -990,6 +990,10 @@ EOF +@@ -990,6 +990,14 @@ EOF if test "$?" = 0 ; then LIBC=gnulibc1 ; fi GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; -+ sw_64:Linux:*:* | sw64:Linux:*:*) -+ UNAME_MACHINE=sw_64 -+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" -+ exit ;; ++ sw_64:Linux:*:*) ++ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in ++ sw) UNAME_MACHINE=sw_64 ;; ++ esac ++ objdump --private-headers /bin/sh | grep -q ld.so.1 ++ if test "$?" = 0 ; then LIBC=gnulibc1 ; fi ++ GUESS=$UNAME_MACHINE-sunway-linux-$LIBC ++ ;; arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; @@ -1008,5 +1013,5 @@ index 2b17826..0861ac6 100644 #include "complex_defs_float.inc" #include "cls_complex_va.inc" -- -2.31.1 +2.20.1 -- Gitee From 71ee159b8f03fe38899ffc90df7dfc7528178bac Mon Sep 17 00:00:00 2001 From: Hailiang Date: Mon, 3 Mar 2025 18:17:19 +0800 Subject: [PATCH 3/3] add sw_64 support --- 0001-test1.patch | 35 ----------------------------------- 1 file changed, 35 deletions(-) delete mode 100644 0001-test1.patch diff --git a/0001-test1.patch b/0001-test1.patch deleted file mode 100644 index 83b84aa..0000000 --- a/0001-test1.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0eb582c348755f9b8f527c066535f95b10deddbf Mon Sep 17 00:00:00 2001 -From: Hailiang -Date: Mon, 3 Mar 2025 18:12:21 +0800 -Subject: [PATCH] test1 - ---- - config.guess | 12 ++++++++---- - 1 file changed, 8 insertions(+), 4 deletions(-) - -diff --git a/config.guess b/config.guess -index fe6f8bc..1239812 100644 ---- a/config.guess -+++ b/config.guess -@@ -990,10 +990,14 @@ EOF - if test "$?" = 0 ; then LIBC=gnulibc1 ; fi - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - ;; -- sw_64:Linux:*:* | sw64:Linux:*:*) -- UNAME_MACHINE=sw_64 -- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" -- exit ;; -+ sw_64:Linux:*:*) -+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in -+ sw) UNAME_MACHINE=sw_64 ;; -+ esac -+ objdump --private-headers /bin/sh | grep -q ld.so.1 -+ if test "$?" = 0 ; then LIBC=gnulibc1 ; fi -+ GUESS=$UNAME_MACHINE-sunway-linux-$LIBC -+ ;; - arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*) - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - ;; --- -2.20.1 - -- Gitee