summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPalmer Dabbelt <palmer@dabbelt.com>2015-01-09 17:51:21 -0800
committerPalmer Dabbelt <palmer@dabbelt.com>2015-01-09 17:51:21 -0800
commitdf4855d6016d7b6d39cbc0b35e06d49db5eb17fb (patch)
tree016a7d9b7c81ab8ee677e12b38cb067290c46d21
parentUpdate the RISC-V toolchain ports (diff)
downloadpalmer-df4855d6016d7b6d39cbc0b35e06d49db5eb17fb.tar.gz
palmer-df4855d6016d7b6d39cbc0b35e06d49db5eb17fb.tar.bz2
palmer-df4855d6016d7b6d39cbc0b35e06d49db5eb17fb.zip
Update the libffi RISCV port
-rw-r--r--dev-libs/libffi/Manifest4
-rw-r--r--dev-libs/libffi/files/libffi-3.1-riscv.patch2879
-rw-r--r--dev-libs/libffi/libffi-3.1-r3.ebuild3
3 files changed, 2019 insertions, 867 deletions
diff --git a/dev-libs/libffi/Manifest b/dev-libs/libffi/Manifest
index 771e13d..3464b58 100644
--- a/dev-libs/libffi/Manifest
+++ b/dev-libs/libffi/Manifest
@@ -1,10 +1,10 @@
AUX libffi-3.0.13-emutramp_pax_proc.patch 911 SHA256 955aa3d87522cb220133fa853bd3a5a7af1fe7cf5cc6b9eb74ffffb9ac563aba SHA512 402712b21feec0f162758adad630ecc588596eaebd2e79bb86802f313e102b8ef6d08eca0580a1aae25dabec3e018c499e2ce1960edc6af9182f67cd8cc9b0e1 WHIRLPOOL 22f76ca6f909c80228958115a8db37fbe5f12e291cdbc1fad672a0903c54a7918e2cee37fdc263e9c350f3c79a7870cc8f7a05789668a8dc87cb8434a6e20f9c
AUX libffi-3.0.13-riscv.patch 53809 SHA256 aedec01c63c1b6de06f8e7e84a02e875e5010fcf7f6bbc7e1ba33e998913a176 SHA512 623adfcb444a35715b8c25a72d4da0453bd089bf446ab86f41145c1573cf37a394ac5512a6761b3cd380a01d4ee9b77302315ee75bb1b2ebf81c583730f311bd WHIRLPOOL 52ae17260e31504734b4628997bed7b0e4e508fbbd8cedc6c6fb9062d959de042dff555d7ac0f66ceb8d7d4797217f9c3045603c8608b6d53bb0a0b6534dcc10
AUX libffi-3.1-execstack.patch 277 SHA256 55e95096d8b2bd82188c62b1316c602738336c0a4b58ccce503936dfc436b1d9 SHA512 1365cb102e6ffacd89b399243cd89ddb29259e373d16fd500d9d98bd40edbd0d79b63df6fb9464247cc2f11628d5c692a25f1c6d9cef19feb857e1232c154d4f WHIRLPOOL 597c3cdb8a28dcc15d724fa4d184956bcd4118803070ba63c1d914eb1a3b4c9720f68404a05ba4ad7ad83714f79ee7856bb8921886511bc7d35b39f33b4b41f0
-AUX libffi-3.1-riscv.patch 54381 SHA256 cad025d4dcb44a1cd77456afecfd7f6122e9eb7ac2b24c50a3cce69189f05015 SHA512 ca9728d0b0181be94f37bd8946a7c2c247054092cceebf5d775ea9a96367aa7461a0f756b9f7f637518b8ac5c491abf7714e625523264263de2e2a32ca45dae3 WHIRLPOOL 2f07b163f5d96f668b4f28068e8268af81317fe97968a8e243c1725de28488800067dac4b3d0832fe78cc7d3a48d550bfc416d1314c7061418c73f4975ba4806
+AUX libffi-3.1-riscv.patch 105494 SHA256 02aa3752799edc56cd964379b6f645fb40a7043468b74839bf957b1862aa6939 SHA512 1f26c2660ccb23c08d679c423c4dd6f98b17301809fc4148956c7edae7659a43080df58e9ee024c719db2fe07bfbf722252076e494f4810a1a6e1f4128358205 WHIRLPOOL 2a46150894d5dd89af7c8c0ea68ca3b5bdd5ace9554612f243b2c5d9e10deb9f2da2fb8206f7cd6ea80b671c5d6a65d969b260ed0ac6cd7c5bcba1a919a539f7
AUX libffi-3.1-typing_error.patch 350 SHA256 2e134e7f347f392499ec9128b220cff467919dfc048922d72689816d9f40ea95 SHA512 6be05ec604da587ded9d50ba57153b7ca24ee52dbed132d08f8653032153d377b2e399b58010e3c84e2106f077696a0cc9507018687af2082aa5ce055ba5fa07 WHIRLPOOL e8613594118774abaa2d79b0cdcbfd57d1c3ca275543423cec70b368e604c78bc7162d582a5b654b378b60a1d765a12b418bd10f8a8693ccbc3e7fdf225be216
AUX libffi-3.2-riscv-closure.patch 742 SHA256 ab4320ddad2377458c1a91409b1db5cd41ce8201e12ee3b13afab2f1bbb7f35c SHA512 159f6de35a5ad63911e905af0f60d41b5f3b8f3a7c8e65c3e83ae7b0780315d99b18de96573c043c4650424069db48f8de321d0c42ec49a7517dc98b8719c6b9 WHIRLPOOL 6a8c8dddb26a0941fa34c1cde59d7e91d2ee5416b5dc4478247b7101df9ead6d065344a14691306df6c944a7c7fafe013056e4bd6a2505a81c27702dd5db1c38
DIST libffi-3.0.13.tar.gz 845747 SHA256 1dddde1400c3bcb7749d398071af88c3e4754058d2d4c0b3696c2f82dc5cf11c SHA512 fc47f5d25197c631754efe05a349edb556d072807ecef19b41f17c1a8f39c95221be64926fbd05b1f8439181df1ddff8fc01462ce3a26005b75159ddc27e6f6a WHIRLPOOL d5b14d48a7b35f7349ec938d0deac62db7022ac4d611ab13bc7a6a2766a47e210fc1663fc8c6d7ee48d421c06b66f558010829ac2c215620c76d0bf7650e1308
DIST libffi-3.1.tar.gz 937214 SHA256 97feeeadca5e21870fa4433bc953d1b3af3f698d5df8a428f68b73cd60aef6eb SHA512 8994973d75facf5ad928c270e17b1a56e24d1543af75b93731a0048e747df27e4190a736b6dc2dca7d43de1d7e88891220304802c10fcccdcebee9c9ffd3d1b9 WHIRLPOOL 19c08cffd39c998fcd762b1e3767b4fd86915427226833411302bebd2d5bcf93d515e6df4a4cab11327595d3966e46442e457fbe09ae986b58bdfb2bb6adb913
EBUILD libffi-3.0.13-r1.ebuild 2404 SHA256 a4236c151f490427e889b47dc030536568f65c6e86613a7ccca669c85f3df5fa SHA512 7af6df8c629152c43afb60ac8ac19220eda34e31b98dfbe1cf0cf7c7eeafb11f062ffe1441a53d48bca936b104e0e2afce3645289feff74f63ecd3c73bb73888 WHIRLPOOL 194c73e539836c429c6b3521db7ee1bc398b1f5637c82dbc6dff04638a65286d00c8876eacb7852f91a306aabf0633108a5972592bf705c732639b73e9eeea0a
-EBUILD libffi-3.1-r3.ebuild 2430 SHA256 677bf4e8e100c44ea0d69ec5d97dccf74e8d413bb73d0dd70f8333afeb582561 SHA512 185e115d4c2f9b7c778ad02c97ff8baae84386ddb4ac8cd3d0c4a04442a2df3c60791b7124f05e37e2664917d3008bfd20efd641ba1f7c1aa3b6955257e4afdd WHIRLPOOL 07eb9ab93318b34758fdc83ab5ffce43f4ef027d570d5329443ec65748c4a787a72aaa0274b47c0767d9bd571e31e535665a05ce01a4658791dce4195c94bff9
+EBUILD libffi-3.1-r3.ebuild 2368 SHA256 85afd60cc867dced69158da6021ea5f985af62a31b0b1313da5cfd54fd29e5ba SHA512 0a61eb4ce6f4316ccb13c8889c8f9c97ac5913a1f3bfffa2c0b978046a0d6c2f5666ff8243551d1c3443fd6bff5cb33ac7b8c5044459b7561e86e8380b5dd98e WHIRLPOOL 33b741990f16504df534449159f5f6dde5c77b58bbcc7387b18681990c8215714615d7987e1a821095902612463921fe6c97aed354e0591714125cba1c05d0a6
diff --git a/dev-libs/libffi/files/libffi-3.1-riscv.patch b/dev-libs/libffi/files/libffi-3.1-riscv.patch
index f606c65..8286e8c 100644
--- a/dev-libs/libffi/files/libffi-3.1-riscv.patch
+++ b/dev-libs/libffi/files/libffi-3.1-riscv.patch
@@ -1,7 +1,7 @@
-diff --git a/Makefile.am b/Makefile.am
-index 1dcdc81..2a6d164 100644
---- a/Makefile.am
-+++ b/Makefile.am
+diff --git a/libffi-3.1/Makefile.am b/libffi-3.1/Makefile.am
+index 1dcdc81..d3e737f 100644
+--- a/libffi-3.1/Makefile.am
++++ b/libffi-3.1/Makefile.am
@@ -8,7 +8,7 @@ SUBDIRS = include testsuite man
EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj \
@@ -11,29 +11,1105 @@ index 1dcdc81..2a6d164 100644
src/alpha/ffitarget.h src/arc/ffi.c src/arc/arcompact.S \
src/arc/ffitarget.h src/arm/ffi.c src/arm/sysv.S \
src/arm/ffitarget.h src/avr32/ffi.c src/avr32/sysv.S \
-@@ -31,6 +31,8 @@ EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj \
+@@ -31,6 +31,7 @@ EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj \
src/powerpc/asm.h src/powerpc/aix.S src/powerpc/darwin.S \
src/powerpc/aix_closure.S src/powerpc/darwin_closure.S \
src/powerpc/ffi_darwin.c src/powerpc/ffitarget.h \
-+ src/riscv/ffi.c src/riscv/rv32.S \
-+ src/riscv/rv64.S src/riscv/ffitarget.h \
++ src/riscv/ffi.c src/riscv/ffitarget.h src/riscv/sysv.S \
src/s390/ffi.c src/s390/sysv.S src/s390/ffitarget.h \
src/sh/ffi.c src/sh/sysv.S src/sh/ffitarget.h src/sh64/ffi.c \
src/sh64/sysv.S src/sh64/ffitarget.h src/sparc/v8.S \
-@@ -121,6 +123,9 @@ endif
+@@ -121,6 +122,9 @@ endif
if MIPS
nodist_libffi_la_SOURCES += src/mips/ffi.c src/mips/o32.S src/mips/n32.S
endif
+if RISCV
-+nodist_libffi_la_SOURCES += src/riscv/ffi.c src/riscv/rv32.S src/riscv/rv64.S
++nodist_libffi_la_SOURCES += src/riscv/ffi.c src/riscv/sysv.S
+endif
if BFIN
nodist_libffi_la_SOURCES += src/bfin/ffi.c src/bfin/sysv.S
endif
-diff --git a/configure.ac b/configure.ac
+diff --git a/libffi-3.1/Makefile.in b/libffi-3.1/Makefile.in
+index 4a57abd..7f4f4fe 100644
+--- a/libffi-3.1/Makefile.in
++++ b/libffi-3.1/Makefile.in
+@@ -82,53 +82,54 @@ host_triplet = @host@
+ target_triplet = @target@
+ @FFI_DEBUG_TRUE@am__append_1 = src/debug.c
+ @MIPS_TRUE@am__append_2 = src/mips/ffi.c src/mips/o32.S src/mips/n32.S
+-@BFIN_TRUE@am__append_3 = src/bfin/ffi.c src/bfin/sysv.S
+-@X86_TRUE@am__append_4 = src/x86/ffi.c src/x86/sysv.S src/x86/win32.S
+-@X86_FREEBSD_TRUE@am__append_5 = src/x86/ffi.c src/x86/freebsd.S src/x86/win32.S
+-@X86_WIN32_TRUE@am__append_6 = src/x86/ffi.c src/x86/win32.S
+-@X86_WIN64_TRUE@am__append_7 = src/x86/ffi.c src/x86/win64.S
+-@X86_DARWIN_TRUE@am__append_8 = src/x86/ffi.c src/x86/darwin.S src/x86/ffi64.c src/x86/darwin64.S
+-@X86_DARWIN32_TRUE@@X86_DARWIN_TRUE@am__append_9 = src/x86/win32.S
+-@SPARC_TRUE@am__append_10 = src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S
+-@ALPHA_TRUE@am__append_11 = src/alpha/ffi.c src/alpha/osf.S
+-@IA64_TRUE@am__append_12 = src/ia64/ffi.c src/ia64/unix.S
+-@M32R_TRUE@am__append_13 = src/m32r/sysv.S src/m32r/ffi.c
+-@M68K_TRUE@am__append_14 = src/m68k/ffi.c src/m68k/sysv.S
+-@M88K_TRUE@am__append_15 = src/m88k/ffi.c src/m88k/obsd.S
+-@MOXIE_TRUE@am__append_16 = src/moxie/ffi.c src/moxie/eabi.S
+-@MICROBLAZE_TRUE@am__append_17 = src/microblaze/ffi.c src/microblaze/sysv.S
+-@NIOS2_TRUE@am__append_18 = src/nios2/sysv.S src/nios2/ffi.c
+-@POWERPC_TRUE@am__append_19 = src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c src/powerpc/sysv.S src/powerpc/ppc_closure.S src/powerpc/linux64.S src/powerpc/linux64_closure.S
+-@POWERPC_AIX_TRUE@am__append_20 = src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/aix_closure.S
+-@POWERPC_DARWIN_TRUE@am__append_21 = src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S
+-@POWERPC_FREEBSD_TRUE@am__append_22 = src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/sysv.S src/powerpc/ppc_closure.S
+-@AARCH64_TRUE@am__append_23 = src/aarch64/sysv.S src/aarch64/ffi.c
+-@ARC_TRUE@am__append_24 = src/arc/arcompact.S src/arc/ffi.c
+-@ARM_TRUE@am__append_25 = src/arm/sysv.S src/arm/ffi.c
+-@ARM_TRUE@@FFI_EXEC_TRAMPOLINE_TABLE_TRUE@am__append_26 = src/arm/trampoline.S
+-@AVR32_TRUE@am__append_27 = src/avr32/sysv.S src/avr32/ffi.c
+-@LIBFFI_CRIS_TRUE@am__append_28 = src/cris/sysv.S src/cris/ffi.c
+-@FRV_TRUE@am__append_29 = src/frv/eabi.S src/frv/ffi.c
+-@S390_TRUE@am__append_30 = src/s390/sysv.S src/s390/ffi.c
+-@X86_64_TRUE@am__append_31 = src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S
+-@SH_TRUE@am__append_32 = src/sh/sysv.S src/sh/ffi.c
+-@SH64_TRUE@am__append_33 = src/sh64/sysv.S src/sh64/ffi.c
+-@PA_LINUX_TRUE@am__append_34 = src/pa/linux.S src/pa/ffi.c
+-@PA_HPUX_TRUE@am__append_35 = src/pa/hpux32.S src/pa/ffi.c
+-@TILE_TRUE@am__append_36 = src/tile/tile.S src/tile/ffi.c
+-@XTENSA_TRUE@am__append_37 = src/xtensa/sysv.S src/xtensa/ffi.c
+-@METAG_TRUE@am__append_38 = src/metag/sysv.S src/metag/ffi.c
+-@VAX_TRUE@am__append_39 = src/vax/elfbsd.S src/vax/ffi.c
++@RISCV_TRUE@am__append_3 = src/riscv/ffi.c src/riscv/sysv.S
++@BFIN_TRUE@am__append_4 = src/bfin/ffi.c src/bfin/sysv.S
++@X86_TRUE@am__append_5 = src/x86/ffi.c src/x86/sysv.S src/x86/win32.S
++@X86_FREEBSD_TRUE@am__append_6 = src/x86/ffi.c src/x86/freebsd.S src/x86/win32.S
++@X86_WIN32_TRUE@am__append_7 = src/x86/ffi.c src/x86/win32.S
++@X86_WIN64_TRUE@am__append_8 = src/x86/ffi.c src/x86/win64.S
++@X86_DARWIN_TRUE@am__append_9 = src/x86/ffi.c src/x86/darwin.S src/x86/ffi64.c src/x86/darwin64.S
++@X86_DARWIN32_TRUE@@X86_DARWIN_TRUE@am__append_10 = src/x86/win32.S
++@SPARC_TRUE@am__append_11 = src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S
++@ALPHA_TRUE@am__append_12 = src/alpha/ffi.c src/alpha/osf.S
++@IA64_TRUE@am__append_13 = src/ia64/ffi.c src/ia64/unix.S
++@M32R_TRUE@am__append_14 = src/m32r/sysv.S src/m32r/ffi.c
++@M68K_TRUE@am__append_15 = src/m68k/ffi.c src/m68k/sysv.S
++@M88K_TRUE@am__append_16 = src/m88k/ffi.c src/m88k/obsd.S
++@MOXIE_TRUE@am__append_17 = src/moxie/ffi.c src/moxie/eabi.S
++@MICROBLAZE_TRUE@am__append_18 = src/microblaze/ffi.c src/microblaze/sysv.S
++@NIOS2_TRUE@am__append_19 = src/nios2/sysv.S src/nios2/ffi.c
++@POWERPC_TRUE@am__append_20 = src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c src/powerpc/sysv.S src/powerpc/ppc_closure.S src/powerpc/linux64.S src/powerpc/linux64_closure.S
++@POWERPC_AIX_TRUE@am__append_21 = src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/aix_closure.S
++@POWERPC_DARWIN_TRUE@am__append_22 = src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S
++@POWERPC_FREEBSD_TRUE@am__append_23 = src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/sysv.S src/powerpc/ppc_closure.S
++@AARCH64_TRUE@am__append_24 = src/aarch64/sysv.S src/aarch64/ffi.c
++@ARC_TRUE@am__append_25 = src/arc/arcompact.S src/arc/ffi.c
++@ARM_TRUE@am__append_26 = src/arm/sysv.S src/arm/ffi.c
++@ARM_TRUE@@FFI_EXEC_TRAMPOLINE_TABLE_TRUE@am__append_27 = src/arm/trampoline.S
++@AVR32_TRUE@am__append_28 = src/avr32/sysv.S src/avr32/ffi.c
++@LIBFFI_CRIS_TRUE@am__append_29 = src/cris/sysv.S src/cris/ffi.c
++@FRV_TRUE@am__append_30 = src/frv/eabi.S src/frv/ffi.c
++@S390_TRUE@am__append_31 = src/s390/sysv.S src/s390/ffi.c
++@X86_64_TRUE@am__append_32 = src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S
++@SH_TRUE@am__append_33 = src/sh/sysv.S src/sh/ffi.c
++@SH64_TRUE@am__append_34 = src/sh64/sysv.S src/sh64/ffi.c
++@PA_LINUX_TRUE@am__append_35 = src/pa/linux.S src/pa/ffi.c
++@PA_HPUX_TRUE@am__append_36 = src/pa/hpux32.S src/pa/ffi.c
++@TILE_TRUE@am__append_37 = src/tile/tile.S src/tile/ffi.c
++@XTENSA_TRUE@am__append_38 = src/xtensa/sysv.S src/xtensa/ffi.c
++@METAG_TRUE@am__append_39 = src/metag/sysv.S src/metag/ffi.c
++@VAX_TRUE@am__append_40 = src/vax/elfbsd.S src/vax/ffi.c
+ # Build debug. Define FFI_DEBUG on the commandline so that, when building with
+ # MSVC, it can link against the debug CRT.
+-@FFI_DEBUG_TRUE@am__append_40 = -DFFI_DEBUG
++@FFI_DEBUG_TRUE@am__append_41 = -DFFI_DEBUG
+ subdir = .
+ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/configure $(am__configure_deps) \
+ $(srcdir)/fficonfig.h.in $(srcdir)/libffi.pc.in depcomp \
+ mdate-sh $(srcdir)/doc/version.texi $(srcdir)/doc/stamp-vti \
+- texinfo.tex README compile config.guess config.sub install-sh \
+- missing ltmain.sh
++ texinfo.tex ChangeLog README compile config.guess config.sub \
++ install-sh missing ltmain.sh
+ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+ am__aclocal_m4_deps = $(top_srcdir)/m4/asmcfi.m4 \
+ $(top_srcdir)/m4/ax_append_flag.m4 \
+@@ -189,61 +190,62 @@ am_libffi_la_OBJECTS = src/prep_cif.lo src/types.lo src/raw_api.lo \
+ @FFI_DEBUG_TRUE@am__objects_1 = src/debug.lo
+ @MIPS_TRUE@am__objects_2 = src/mips/ffi.lo src/mips/o32.lo \
+ @MIPS_TRUE@ src/mips/n32.lo
+-@BFIN_TRUE@am__objects_3 = src/bfin/ffi.lo src/bfin/sysv.lo
+-@X86_TRUE@am__objects_4 = src/x86/ffi.lo src/x86/sysv.lo \
++@RISCV_TRUE@am__objects_3 = src/riscv/ffi.lo src/riscv/sysv.lo
++@BFIN_TRUE@am__objects_4 = src/bfin/ffi.lo src/bfin/sysv.lo
++@X86_TRUE@am__objects_5 = src/x86/ffi.lo src/x86/sysv.lo \
+ @X86_TRUE@ src/x86/win32.lo
+-@X86_FREEBSD_TRUE@am__objects_5 = src/x86/ffi.lo src/x86/freebsd.lo \
++@X86_FREEBSD_TRUE@am__objects_6 = src/x86/ffi.lo src/x86/freebsd.lo \
+ @X86_FREEBSD_TRUE@ src/x86/win32.lo
+-@X86_WIN32_TRUE@am__objects_6 = src/x86/ffi.lo src/x86/win32.lo
+-@X86_WIN64_TRUE@am__objects_7 = src/x86/ffi.lo src/x86/win64.lo
+-@X86_DARWIN_TRUE@am__objects_8 = src/x86/ffi.lo src/x86/darwin.lo \
++@X86_WIN32_TRUE@am__objects_7 = src/x86/ffi.lo src/x86/win32.lo
++@X86_WIN64_TRUE@am__objects_8 = src/x86/ffi.lo src/x86/win64.lo
++@X86_DARWIN_TRUE@am__objects_9 = src/x86/ffi.lo src/x86/darwin.lo \
+ @X86_DARWIN_TRUE@ src/x86/ffi64.lo src/x86/darwin64.lo
+-@X86_DARWIN32_TRUE@@X86_DARWIN_TRUE@am__objects_9 = src/x86/win32.lo
+-@SPARC_TRUE@am__objects_10 = src/sparc/ffi.lo src/sparc/v8.lo \
++@X86_DARWIN32_TRUE@@X86_DARWIN_TRUE@am__objects_10 = src/x86/win32.lo
++@SPARC_TRUE@am__objects_11 = src/sparc/ffi.lo src/sparc/v8.lo \
+ @SPARC_TRUE@ src/sparc/v9.lo
+-@ALPHA_TRUE@am__objects_11 = src/alpha/ffi.lo src/alpha/osf.lo
+-@IA64_TRUE@am__objects_12 = src/ia64/ffi.lo src/ia64/unix.lo
+-@M32R_TRUE@am__objects_13 = src/m32r/sysv.lo src/m32r/ffi.lo
+-@M68K_TRUE@am__objects_14 = src/m68k/ffi.lo src/m68k/sysv.lo
+-@M88K_TRUE@am__objects_15 = src/m88k/ffi.lo src/m88k/obsd.lo
+-@MOXIE_TRUE@am__objects_16 = src/moxie/ffi.lo src/moxie/eabi.lo
+-@MICROBLAZE_TRUE@am__objects_17 = src/microblaze/ffi.lo \
++@ALPHA_TRUE@am__objects_12 = src/alpha/ffi.lo src/alpha/osf.lo
++@IA64_TRUE@am__objects_13 = src/ia64/ffi.lo src/ia64/unix.lo
++@M32R_TRUE@am__objects_14 = src/m32r/sysv.lo src/m32r/ffi.lo
++@M68K_TRUE@am__objects_15 = src/m68k/ffi.lo src/m68k/sysv.lo
++@M88K_TRUE@am__objects_16 = src/m88k/ffi.lo src/m88k/obsd.lo
++@MOXIE_TRUE@am__objects_17 = src/moxie/ffi.lo src/moxie/eabi.lo
++@MICROBLAZE_TRUE@am__objects_18 = src/microblaze/ffi.lo \
+ @MICROBLAZE_TRUE@ src/microblaze/sysv.lo
+-@NIOS2_TRUE@am__objects_18 = src/nios2/sysv.lo src/nios2/ffi.lo
+-@POWERPC_TRUE@am__objects_19 = src/powerpc/ffi.lo \
++@NIOS2_TRUE@am__objects_19 = src/nios2/sysv.lo src/nios2/ffi.lo
++@POWERPC_TRUE@am__objects_20 = src/powerpc/ffi.lo \
+ @POWERPC_TRUE@ src/powerpc/ffi_sysv.lo \
+ @POWERPC_TRUE@ src/powerpc/ffi_linux64.lo src/powerpc/sysv.lo \
+ @POWERPC_TRUE@ src/powerpc/ppc_closure.lo \
+ @POWERPC_TRUE@ src/powerpc/linux64.lo \
+ @POWERPC_TRUE@ src/powerpc/linux64_closure.lo
+-@POWERPC_AIX_TRUE@am__objects_20 = src/powerpc/ffi_darwin.lo \
++@POWERPC_AIX_TRUE@am__objects_21 = src/powerpc/ffi_darwin.lo \
+ @POWERPC_AIX_TRUE@ src/powerpc/aix.lo \
+ @POWERPC_AIX_TRUE@ src/powerpc/aix_closure.lo
+-@POWERPC_DARWIN_TRUE@am__objects_21 = src/powerpc/ffi_darwin.lo \
++@POWERPC_DARWIN_TRUE@am__objects_22 = src/powerpc/ffi_darwin.lo \
+ @POWERPC_DARWIN_TRUE@ src/powerpc/darwin.lo \
+ @POWERPC_DARWIN_TRUE@ src/powerpc/darwin_closure.lo
+-@POWERPC_FREEBSD_TRUE@am__objects_22 = src/powerpc/ffi.lo \
++@POWERPC_FREEBSD_TRUE@am__objects_23 = src/powerpc/ffi.lo \
+ @POWERPC_FREEBSD_TRUE@ src/powerpc/ffi_sysv.lo \
+ @POWERPC_FREEBSD_TRUE@ src/powerpc/sysv.lo \
+ @POWERPC_FREEBSD_TRUE@ src/powerpc/ppc_closure.lo
+-@AARCH64_TRUE@am__objects_23 = src/aarch64/sysv.lo src/aarch64/ffi.lo
+-@ARC_TRUE@am__objects_24 = src/arc/arcompact.lo src/arc/ffi.lo
+-@ARM_TRUE@am__objects_25 = src/arm/sysv.lo src/arm/ffi.lo
+-@ARM_TRUE@@FFI_EXEC_TRAMPOLINE_TABLE_TRUE@am__objects_26 = src/arm/trampoline.lo
+-@AVR32_TRUE@am__objects_27 = src/avr32/sysv.lo src/avr32/ffi.lo
+-@LIBFFI_CRIS_TRUE@am__objects_28 = src/cris/sysv.lo src/cris/ffi.lo
+-@FRV_TRUE@am__objects_29 = src/frv/eabi.lo src/frv/ffi.lo
+-@S390_TRUE@am__objects_30 = src/s390/sysv.lo src/s390/ffi.lo
+-@X86_64_TRUE@am__objects_31 = src/x86/ffi64.lo src/x86/unix64.lo \
++@AARCH64_TRUE@am__objects_24 = src/aarch64/sysv.lo src/aarch64/ffi.lo
++@ARC_TRUE@am__objects_25 = src/arc/arcompact.lo src/arc/ffi.lo
++@ARM_TRUE@am__objects_26 = src/arm/sysv.lo src/arm/ffi.lo
++@ARM_TRUE@@FFI_EXEC_TRAMPOLINE_TABLE_TRUE@am__objects_27 = src/arm/trampoline.lo
++@AVR32_TRUE@am__objects_28 = src/avr32/sysv.lo src/avr32/ffi.lo
++@LIBFFI_CRIS_TRUE@am__objects_29 = src/cris/sysv.lo src/cris/ffi.lo
++@FRV_TRUE@am__objects_30 = src/frv/eabi.lo src/frv/ffi.lo
++@S390_TRUE@am__objects_31 = src/s390/sysv.lo src/s390/ffi.lo
++@X86_64_TRUE@am__objects_32 = src/x86/ffi64.lo src/x86/unix64.lo \
+ @X86_64_TRUE@ src/x86/ffi.lo src/x86/sysv.lo
+-@SH_TRUE@am__objects_32 = src/sh/sysv.lo src/sh/ffi.lo
+-@SH64_TRUE@am__objects_33 = src/sh64/sysv.lo src/sh64/ffi.lo
+-@PA_LINUX_TRUE@am__objects_34 = src/pa/linux.lo src/pa/ffi.lo
+-@PA_HPUX_TRUE@am__objects_35 = src/pa/hpux32.lo src/pa/ffi.lo
+-@TILE_TRUE@am__objects_36 = src/tile/tile.lo src/tile/ffi.lo
+-@XTENSA_TRUE@am__objects_37 = src/xtensa/sysv.lo src/xtensa/ffi.lo
+-@METAG_TRUE@am__objects_38 = src/metag/sysv.lo src/metag/ffi.lo
+-@VAX_TRUE@am__objects_39 = src/vax/elfbsd.lo src/vax/ffi.lo
++@SH_TRUE@am__objects_33 = src/sh/sysv.lo src/sh/ffi.lo
++@SH64_TRUE@am__objects_34 = src/sh64/sysv.lo src/sh64/ffi.lo
++@PA_LINUX_TRUE@am__objects_35 = src/pa/linux.lo src/pa/ffi.lo
++@PA_HPUX_TRUE@am__objects_36 = src/pa/hpux32.lo src/pa/ffi.lo
++@TILE_TRUE@am__objects_37 = src/tile/tile.lo src/tile/ffi.lo
++@XTENSA_TRUE@am__objects_38 = src/xtensa/sysv.lo src/xtensa/ffi.lo
++@METAG_TRUE@am__objects_39 = src/metag/sysv.lo src/metag/ffi.lo
++@VAX_TRUE@am__objects_40 = src/vax/elfbsd.lo src/vax/ffi.lo
+ nodist_libffi_la_OBJECTS = $(am__objects_1) $(am__objects_2) \
+ $(am__objects_3) $(am__objects_4) $(am__objects_5) \
+ $(am__objects_6) $(am__objects_7) $(am__objects_8) \
+@@ -257,7 +259,7 @@ nodist_libffi_la_OBJECTS = $(am__objects_1) $(am__objects_2) \
+ $(am__objects_30) $(am__objects_31) $(am__objects_32) \
+ $(am__objects_33) $(am__objects_34) $(am__objects_35) \
+ $(am__objects_36) $(am__objects_37) $(am__objects_38) \
+- $(am__objects_39)
++ $(am__objects_39) $(am__objects_40)
+ libffi_la_OBJECTS = $(am_libffi_la_OBJECTS) \
+ $(nodist_libffi_la_OBJECTS)
+ AM_V_lt = $(am__v_lt_@AM_V@)
+@@ -268,10 +270,10 @@ libffi_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libffi_la_LDFLAGS) $(LDFLAGS) -o $@
+ libffi_convenience_la_LIBADD =
+-am__objects_40 = src/prep_cif.lo src/types.lo src/raw_api.lo \
++am__objects_41 = src/prep_cif.lo src/types.lo src/raw_api.lo \
+ src/java_raw_api.lo src/closures.lo
+-am_libffi_convenience_la_OBJECTS = $(am__objects_40)
+-am__objects_41 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \
++am_libffi_convenience_la_OBJECTS = $(am__objects_41)
++am__objects_42 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \
+ $(am__objects_4) $(am__objects_5) $(am__objects_6) \
+ $(am__objects_7) $(am__objects_8) $(am__objects_9) \
+ $(am__objects_10) $(am__objects_11) $(am__objects_12) \
+@@ -283,8 +285,9 @@ am__objects_41 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \
+ $(am__objects_28) $(am__objects_29) $(am__objects_30) \
+ $(am__objects_31) $(am__objects_32) $(am__objects_33) \
+ $(am__objects_34) $(am__objects_35) $(am__objects_36) \
+- $(am__objects_37) $(am__objects_38) $(am__objects_39)
+-nodist_libffi_convenience_la_OBJECTS = $(am__objects_41)
++ $(am__objects_37) $(am__objects_38) $(am__objects_39) \
++ $(am__objects_40)
++nodist_libffi_convenience_la_OBJECTS = $(am__objects_42)
+ libffi_convenience_la_OBJECTS = $(am_libffi_convenience_la_OBJECTS) \
+ $(nodist_libffi_convenience_la_OBJECTS)
+ AM_V_P = $(am__v_P_@AM_V@)
+@@ -606,7 +609,7 @@ ACLOCAL_AMFLAGS = -I m4
+ SUBDIRS = include testsuite man
+ EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj \
+ src/aarch64/ffi.c src/aarch64/ffitarget.h src/aarch64/sysv.S \
+- src/alpha/ffi.c src/alpha/osf.S \
++ src/alpha/ffi.c src/alpha/osf.S \
+ src/alpha/ffitarget.h src/arc/ffi.c src/arc/arcompact.S \
+ src/arc/ffitarget.h src/arm/ffi.c src/arm/sysv.S \
+ src/arm/ffitarget.h src/avr32/ffi.c src/avr32/sysv.S \
+@@ -629,6 +632,7 @@ EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj \
+ src/powerpc/asm.h src/powerpc/aix.S src/powerpc/darwin.S \
+ src/powerpc/aix_closure.S src/powerpc/darwin_closure.S \
+ src/powerpc/ffi_darwin.c src/powerpc/ffitarget.h \
++ src/riscv/ffi.c src/riscv/ffitarget.h src/riscv/sysv.S \
+ src/s390/ffi.c src/s390/sysv.S src/s390/ffitarget.h \
+ src/sh/ffi.c src/sh/sysv.S src/sh/ffitarget.h src/sh64/ffi.c \
+ src/sh64/sysv.S src/sh64/ffitarget.h src/sparc/v8.S \
+@@ -714,11 +718,11 @@ nodist_libffi_la_SOURCES = $(am__append_1) $(am__append_2) \
+ $(am__append_30) $(am__append_31) $(am__append_32) \
+ $(am__append_33) $(am__append_34) $(am__append_35) \
+ $(am__append_36) $(am__append_37) $(am__append_38) \
+- $(am__append_39)
++ $(am__append_39) $(am__append_40)
+ libffi_convenience_la_SOURCES = $(libffi_la_SOURCES)
+ nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES)
+ LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/libtool-ldflags $(LDFLAGS))
+-AM_CFLAGS = $(am__append_40)
++AM_CFLAGS = $(am__append_41)
+ libffi_la_LDFLAGS = -no-undefined -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LTLDFLAGS) $(AM_LTLDFLAGS)
+ AM_CPPFLAGS = -I. -I$(top_srcdir)/include -Iinclude -I$(top_srcdir)/src
+ AM_CCASFLAGS = $(AM_CPPFLAGS)
+@@ -848,6 +852,16 @@ src/mips/o32.lo: src/mips/$(am__dirstamp) \
+ src/mips/$(DEPDIR)/$(am__dirstamp)
+ src/mips/n32.lo: src/mips/$(am__dirstamp) \
+ src/mips/$(DEPDIR)/$(am__dirstamp)
++src/riscv/$(am__dirstamp):
++ @$(MKDIR_P) src/riscv
++ @: > src/riscv/$(am__dirstamp)
++src/riscv/$(DEPDIR)/$(am__dirstamp):
++ @$(MKDIR_P) src/riscv/$(DEPDIR)
++ @: > src/riscv/$(DEPDIR)/$(am__dirstamp)
++src/riscv/ffi.lo: src/riscv/$(am__dirstamp) \
++ src/riscv/$(DEPDIR)/$(am__dirstamp)
++src/riscv/sysv.lo: src/riscv/$(am__dirstamp) \
++ src/riscv/$(DEPDIR)/$(am__dirstamp)
+ src/bfin/$(am__dirstamp):
+ @$(MKDIR_P) src/bfin
+ @: > src/bfin/$(am__dirstamp)
+@@ -1195,6 +1209,8 @@ mostlyclean-compile:
+ -rm -f src/pa/*.lo
+ -rm -f src/powerpc/*.$(OBJEXT)
+ -rm -f src/powerpc/*.lo
++ -rm -f src/riscv/*.$(OBJEXT)
++ -rm -f src/riscv/*.lo
+ -rm -f src/s390/*.$(OBJEXT)
+ -rm -f src/s390/*.lo
+ -rm -f src/sh/*.$(OBJEXT)
+@@ -1272,6 +1288,8 @@ distclean-compile:
+ @AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/linux64_closure.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/ppc_closure.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/sysv.Plo@am__quote@
++@AMDEP_TRUE@@am__include@ @am__quote@src/riscv/$(DEPDIR)/ffi.Plo@am__quote@
++@AMDEP_TRUE@@am__include@ @am__quote@src/riscv/$(DEPDIR)/sysv.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@src/s390/$(DEPDIR)/ffi.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@src/s390/$(DEPDIR)/sysv.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@src/sh/$(DEPDIR)/ffi.Plo@am__quote@
+@@ -1370,6 +1388,7 @@ clean-libtool:
+ -rm -rf src/nios2/.libs src/nios2/_libs
+ -rm -rf src/pa/.libs src/pa/_libs
+ -rm -rf src/powerpc/.libs src/powerpc/_libs
++ -rm -rf src/riscv/.libs src/riscv/_libs
+ -rm -rf src/s390/.libs src/s390/_libs
+ -rm -rf src/sh/.libs src/sh/_libs
+ -rm -rf src/sh64/.libs src/sh64/_libs
+@@ -1932,6 +1951,8 @@ distclean-generic:
+ -rm -f src/pa/$(am__dirstamp)
+ -rm -f src/powerpc/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/powerpc/$(am__dirstamp)
++ -rm -f src/riscv/$(DEPDIR)/$(am__dirstamp)
++ -rm -f src/riscv/$(am__dirstamp)
+ -rm -f src/s390/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/s390/$(am__dirstamp)
+ -rm -f src/sh/$(DEPDIR)/$(am__dirstamp)
+@@ -1960,7 +1981,7 @@ clean-am: clean-aminfo clean-generic clean-libtool \
+
+ 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/frv/$(DEPDIR) src/ia64/$(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/pa/$(DEPDIR) src/powerpc/$(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/frv/$(DEPDIR) src/ia64/$(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/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 -f Makefile
+ distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-hdr distclean-libtool distclean-tags
+@@ -2099,7 +2120,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/frv/$(DEPDIR) src/ia64/$(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/pa/$(DEPDIR) src/powerpc/$(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/frv/$(DEPDIR) src/ia64/$(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/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 -f Makefile
+ maintainer-clean-am: distclean-am maintainer-clean-aminfo \
+ maintainer-clean-generic maintainer-clean-vti
+diff --git a/libffi-3.1/README.md b/libffi-3.1/README.md
+new file mode 100644
+index 0000000..d1a0b77
+--- /dev/null
++++ b/libffi-3.1/README.md
+@@ -0,0 +1,23 @@
++RISC-V Port of libffi
++=====================
++
++Compile and run:
++
++```
++./configure --host=riscv64-unknown-elf
++make
++```
++
++Run tests in Spike:
++
++```
++make check RUNTESTFLAGS="--target_board=riscv-sim --all"
++```
++
++Run an individual test:
++
++Go to `testsuite/libffi.call` directory and run:
++
++```
++../../misc/run_test.sh <test_name.c>
++```
+diff --git a/libffi-3.1/aclocal.m4 b/libffi-3.1/aclocal.m4
+index 6292fba..db932a6 100644
+--- a/libffi-3.1/aclocal.m4
++++ b/libffi-3.1/aclocal.m4
+@@ -1,4 +1,4 @@
+-# generated automatically by aclocal 1.13.4 -*- Autoconf -*-
++# generated automatically by aclocal 1.14.1 -*- Autoconf -*-
+
+ # Copyright (C) 1996-2013 Free Software Foundation, Inc.
+
+@@ -515,7 +515,7 @@ AC_CACHE_CHECK([whether deplibs are loaded by dlopen],
+ # at 6.2 and later dlopen does load deplibs.
+ lt_cv_sys_dlopen_deplibs=yes
+ ;;
+- netbsd*)
++ netbsd* | netbsdelf*-gnu)
+ lt_cv_sys_dlopen_deplibs=yes
+ ;;
+ openbsd*)
+@@ -850,10 +850,10 @@ dnl AC_DEFUN([AC_LTDL_DLSYM_USCORE], [])
+ # generated from the m4 files accompanying Automake X.Y.
+ # (This private macro should not be called outside this file.)
+ AC_DEFUN([AM_AUTOMAKE_VERSION],
+-[am__api_version='1.13'
++[am__api_version='1.14'
+ dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+ dnl require some minimum version. Point them to the right macro.
+-m4_if([$1], [1.13.4], [],
++m4_if([$1], [1.14.1], [],
+ [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+ ])
+
+@@ -869,7 +869,7 @@ m4_define([_AM_AUTOCONF_VERSION], [])
+ # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+ # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+ AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+-[AM_AUTOMAKE_VERSION([1.13.4])dnl
++[AM_AUTOMAKE_VERSION([1.14.1])dnl
+ m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+ _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+@@ -1256,6 +1256,12 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+ # This macro actually does too much. Some checks are only needed if
+ # your package does certain things. But this isn't really a big deal.
+
++dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
++m4_define([AC_PROG_CC],
++m4_defn([AC_PROG_CC])
++[_AM_PROG_CC_C_O
++])
++
+ # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+ # AM_INIT_AUTOMAKE([OPTIONS])
+ # -----------------------------------------------
+@@ -1364,7 +1370,48 @@ dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
+ AC_CONFIG_COMMANDS_PRE(dnl
+ [m4_provide_if([_AM_COMPILER_EXEEXT],
+ [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+-])
++
++# POSIX will say in a future version that running "rm -f" with no argument
++# is OK; and we want to be able to make that assumption in our Makefile
++# recipes. So use an aggressive probe to check that the usage we want is
++# actually supported "in the wild" to an acceptable degree.
++# See automake bug#10828.
++# To make any issue more visible, cause the running configure to be aborted
++# by default if the 'rm' program in use doesn't match our expectations; the
++# user can still override this though.
++if rm -f && rm -fr && rm -rf; then : OK; else
++ cat >&2 <<'END'
++Oops!
++
++Your 'rm' program seems unable to run without file operands specified
++on the command line, even when the '-f' option is present. This is contrary
++to the behaviour of most rm programs out there, and not conforming with
++the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
++
++Please tell bug-automake@gnu.org about your system, including the value
++of your $PATH and any error possibly output before this message. This
++can help us improve future automake versions.
++
++END
++ if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
++ echo 'Configuration will proceed anyway, since you have set the' >&2
++ echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
++ echo >&2
++ else
++ cat >&2 <<'END'
++Aborting the configuration process, to ensure you take notice of the issue.
++
++You can download and install GNU coreutils to get an 'rm' implementation
++that behaves properly: <http://www.gnu.org/software/coreutils/>.
++
++If you want to complete the configuration process using your problematic
++'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
++to "yes", and re-run configure.
++
++END
++ AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
++ fi
++fi])
+
+ dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
+ dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+@@ -1372,7 +1419,6 @@ dnl mangled by Autoconf and run in a shell conditional statement.
+ m4_define([_AC_COMPILER_EXEEXT],
+ m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+-
+ # When config.status generates a header, we must update the stamp-h file.
+ # This file resides in the same directory as the config header
+ # that is generated. The stamp files are numbered to have different names.
+@@ -1520,38 +1566,6 @@ AC_MSG_RESULT([$_am_result])
+ rm -f confinc confmf
+ ])
+
+-# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+-#
+-# This file is free software; the Free Software Foundation
+-# gives unlimited permission to copy and/or distribute it,
+-# with or without modifications, as long as this notice is preserved.
+-
+-# AM_PROG_CC_C_O
+-# --------------
+-# Like AC_PROG_CC_C_O, but changed for automake.
+-AC_DEFUN([AM_PROG_CC_C_O],
+-[AC_REQUIRE([AC_PROG_CC_C_O])dnl
+-AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+-AC_REQUIRE_AUX_FILE([compile])dnl
+-# FIXME: we rely on the cache variable name because
+-# there is no other way.
+-set dummy $CC
+-am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']`
+-eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o
+-if test "$am_t" != yes; then
+- # Losing compiler, so override with the script.
+- # FIXME: It is wrong to rewrite CC.
+- # But if we don't then we get into trouble of one sort or another.
+- # A longer-term fix would be to have automake use am__CC in this case,
+- # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+- CC="$am_aux_dir/compile $CC"
+-fi
+-dnl Make sure AC_PROG_CC is never called again, or it will override our
+-dnl setting of CC.
+-m4_define([AC_PROG_CC],
+- [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])])
+-])
+-
+ # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
+
+ # Copyright (C) 1997-2013 Free Software Foundation, Inc.
+@@ -1622,6 +1636,70 @@ AC_DEFUN([_AM_SET_OPTIONS],
+ AC_DEFUN([_AM_IF_OPTION],
+ [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
++# Copyright (C) 1999-2013 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# _AM_PROG_CC_C_O
++# ---------------
++# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC
++# to automatically call this.
++AC_DEFUN([_AM_PROG_CC_C_O],
++[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
++AC_REQUIRE_AUX_FILE([compile])dnl
++AC_LANG_PUSH([C])dnl
++AC_CACHE_CHECK(
++ [whether $CC understands -c and -o together],
++ [am_cv_prog_cc_c_o],
++ [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
++ # Make sure it works both with $CC and with simple cc.
++ # Following AC_PROG_CC_C_O, we do the test twice because some
++ # compilers refuse to overwrite an existing .o file with -o,
++ # though they will create one.
++ am_cv_prog_cc_c_o=yes
++ for am_i in 1 2; do
++ if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \
++ && test -f conftest2.$ac_objext; then
++ : OK
++ else
++ am_cv_prog_cc_c_o=no
++ break
++ fi
++ done
++ rm -f core conftest*
++ unset am_i])
++if test "$am_cv_prog_cc_c_o" != yes; then
++ # Losing compiler, so override with the script.
++ # FIXME: It is wrong to rewrite CC.
++ # But if we don't then we get into trouble of one sort or another.
++ # A longer-term fix would be to have automake use am__CC in this case,
++ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
++ CC="$am_aux_dir/compile $CC"
++fi
++AC_LANG_POP([C])])
++
++# For backward compatibility.
++AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
++
++# Copyright (C) 2001-2013 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# AM_RUN_LOG(COMMAND)
++# -------------------
++# Run COMMAND, save the exit status in ac_status, and log it.
++# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
++AC_DEFUN([AM_RUN_LOG],
++[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
++ ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
++ (exit $ac_status); }])
++
+ # Check to make sure that the build environment is sane. -*- Autoconf -*-
+
+ # Copyright (C) 1996-2013 Free Software Foundation, Inc.
+diff --git a/libffi-3.1/config.sub b/libffi-3.1/config.sub
+index c765b34..5d14ffc 100755
+--- a/libffi-3.1/config.sub
++++ b/libffi-3.1/config.sub
+@@ -1,8 +1,8 @@
+ #! /bin/sh
+ # Configuration validation subroutine script.
+-# Copyright 1992-2013 Free Software Foundation, Inc.
++# Copyright 1992-2014 Free Software Foundation, Inc.
+
+-timestamp='2013-04-24'
++timestamp='2014-05-01'
+
+ # This file is free software; you can redistribute it and/or modify it
+ # under the terms of the GNU General Public License as published by
+@@ -68,7 +68,7 @@ Report bugs and patches to <config-patches@gnu.org>."
+ version="\
+ GNU config.sub ($timestamp)
+
+-Copyright 1992-2013 Free Software Foundation, Inc.
++Copyright 1992-2014 Free Software Foundation, Inc.
+
+ This is free software; see the source for copying conditions. There is NO
+ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+@@ -257,7 +257,7 @@ case $basic_machine in
+ | avr | avr32 \
+ | be32 | be64 \
+ | bfin \
+- | c4x | clipper \
++ | c4x | c8051 | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | epiphany \
+ | fido | fr30 | frv \
+@@ -265,6 +265,7 @@ case $basic_machine in
+ | hexagon \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
++ | k1om \
+ | le32 | le64 \
+ | lm32 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+@@ -282,8 +283,10 @@ case $basic_machine in
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
++ | mipsisa32r6 | mipsisa32r6el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
++ | mipsisa64r6 | mipsisa64r6el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipsr5900 | mipsr5900el \
+@@ -295,11 +298,11 @@ case $basic_machine in
+ | nds32 | nds32le | nds32be \
+ | nios | nios2 | nios2eb | nios2el \
+ | ns16k | ns32k \
+- | open8 \
+- | or1k | or32 \
++ | open8 | or1k | or1knd | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle \
+ | pyramid \
++ | riscv \
+ | rl78 | rx \
+ | score \
+ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+@@ -324,7 +327,7 @@ case $basic_machine in
+ c6x)
+ basic_machine=tic6x-unknown
+ ;;
+- m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
++ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+@@ -372,7 +375,7 @@ case $basic_machine in
+ | be32-* | be64-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* \
+- | clipper-* | craynv-* | cydra-* \
++ | c8051-* | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+@@ -381,6 +384,7 @@ case $basic_machine in
+ | hexagon-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
++ | k1om-* \
+ | le32-* | le64-* \
+ | lm32-* \
+ | m32c-* | m32r-* | m32rle-* \
+@@ -400,8 +404,10 @@ case $basic_machine in
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
++ | mipsisa32r6-* | mipsisa32r6el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
++ | mipsisa64r6-* | mipsisa64r6el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipsr5900-* | mipsr5900el-* \
+@@ -413,6 +419,7 @@ case $basic_machine in
+ | nios-* | nios2-* | nios2eb-* | nios2el-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | open8-* \
++ | or1k*-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+@@ -794,7 +801,7 @@ case $basic_machine in
+ os=-mingw64
+ ;;
+ mingw32)
+- basic_machine=i386-pc
++ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ mingw32ce)
+@@ -830,7 +837,7 @@ case $basic_machine in
+ basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+ ;;
+ msys)
+- basic_machine=i386-pc
++ basic_machine=i686-pc
+ os=-msys
+ ;;
+ mvs)
+@@ -1006,7 +1013,7 @@ case $basic_machine in
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+- ppc64-* | ppc64p7-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
++ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+@@ -1374,7 +1381,7 @@ case $os in
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+- | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
++ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+@@ -1546,6 +1553,9 @@ case $basic_machine in
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
++ c8051-*)
++ os=-elf
++ ;;
+ hexagon-*)
+ os=-elf
+ ;;
+@@ -1589,9 +1599,6 @@ case $basic_machine in
+ mips*-*)
+ os=-elf
+ ;;
+- or1k-*)
+- os=-elf
+- ;;
+ or32-*)
+ os=-coff
+ ;;
+diff --git a/libffi-3.1/configure b/libffi-3.1/configure
+index a05785e..d9fee55 100755
+--- a/libffi-3.1/configure
++++ b/libffi-3.1/configure
+@@ -726,6 +726,8 @@ BFIN_FALSE
+ BFIN_TRUE
+ MIPS_FALSE
+ MIPS_TRUE
++RISCV_FALSE
++RISCV_TRUE
+ AM_LTLDFLAGS
+ AM_RUNTESTFLAGS
+ TESTSUBDIR_FALSE
+@@ -2959,7 +2961,7 @@ ax_enable_builddir_auxdir="$am_aux_dir"
+ ac_config_commands="$ac_config_commands buildir"
+
+
+-am__api_version='1.13'
++am__api_version='1.14'
+
+ # Find a good install program. We prefer a C program (faster),
+ # so one script is as good as another. But avoid the broken or
+@@ -3493,6 +3495,47 @@ am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
+
+
+
++# POSIX will say in a future version that running "rm -f" with no argument
++# is OK; and we want to be able to make that assumption in our Makefile
++# recipes. So use an aggressive probe to check that the usage we want is
++# actually supported "in the wild" to an acceptable degree.
++# See automake bug#10828.
++# To make any issue more visible, cause the running configure to be aborted
++# by default if the 'rm' program in use doesn't match our expectations; the
++# user can still override this though.
++if rm -f && rm -fr && rm -rf; then : OK; else
++ cat >&2 <<'END'
++Oops!
++
++Your 'rm' program seems unable to run without file operands specified
++on the command line, even when the '-f' option is present. This is contrary
++to the behaviour of most rm programs out there, and not conforming with
++the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
++
++Please tell bug-automake@gnu.org about your system, including the value
++of your $PATH and any error possibly output before this message. This
++can help us improve future automake versions.
++
++END
++ if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
++ echo 'Configuration will proceed anyway, since you have set the' >&2
++ echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
++ echo >&2
++ else
++ cat >&2 <<'END'
++Aborting the configuration process, to ensure you take notice of the issue.
++
++You can download and install GNU coreutils to get an 'rm' implementation
++that behaves properly: <http://www.gnu.org/software/coreutils/>.
++
++If you want to complete the configuration process using your problematic
++'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
++to "yes", and re-run configure.
++
++END
++ as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5
++ fi
++fi
+
+ # The same as in boehm-gc and libstdc++. Have to borrow it from there.
+ # We must force CC to /not/ be precious variables; otherwise
+@@ -4292,6 +4335,65 @@ ac_cpp='$CPP $CPPFLAGS'
+ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ ac_compiler_gnu=$ac_cv_c_compiler_gnu
++
++ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
++$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
++if ${am_cv_prog_cc_c_o+:} false; then :
++ $as_echo_n "(cached) " >&6
++else
++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++
++int
++main ()
++{
++
++ ;
++ return 0;
++}
++_ACEOF
++ # Make sure it works both with $CC and with simple cc.
++ # Following AC_PROG_CC_C_O, we do the test twice because some
++ # compilers refuse to overwrite an existing .o file with -o,
++ # though they will create one.
++ am_cv_prog_cc_c_o=yes
++ for am_i in 1 2; do
++ if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
++ ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } \
++ && test -f conftest2.$ac_objext; then
++ : OK
++ else
++ am_cv_prog_cc_c_o=no
++ break
++ fi
++ done
++ rm -f core conftest*
++ unset am_i
++fi
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
++$as_echo "$am_cv_prog_cc_c_o" >&6; }
++if test "$am_cv_prog_cc_c_o" != yes; then
++ # Losing compiler, so override with the script.
++ # FIXME: It is wrong to rewrite CC.
++ # But if we don't then we get into trouble of one sort or another.
++ # A longer-term fix would be to have automake use am__CC in this case,
++ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
++ CC="$am_aux_dir/compile $CC"
++fi
++ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++
+ DEPDIR="${am__leading_dot}deps"
+
+ ac_config_commands="$ac_config_commands depfiles"
+@@ -5008,131 +5110,6 @@ else
+ fi
+
+
+-if test "x$CC" != xcc; then
+- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5
+-$as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; }
+-else
+- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5
+-$as_echo_n "checking whether cc understands -c and -o together... " >&6; }
+-fi
+-set dummy $CC; ac_cc=`$as_echo "$2" |
+- sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
+-if eval \${ac_cv_prog_cc_${ac_cc}_c_o+:} false; then :
+- $as_echo_n "(cached) " >&6
+-else
+- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+-/* end confdefs.h. */
+-
+-int
+-main ()
+-{
+-
+- ;
+- return 0;
+-}
+-_ACEOF
+-# Make sure it works both with $CC and with simple cc.
+-# We do the test twice because some compilers refuse to overwrite an
+-# existing .o file with -o, though they will create one.
+-ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
+-rm -f conftest2.*
+-if { { case "(($ac_try" in
+- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+- *) ac_try_echo=$ac_try;;
+-esac
+-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+-$as_echo "$ac_try_echo"; } >&5
+- (eval "$ac_try") 2>&5
+- ac_status=$?
+- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+- test $ac_status = 0; } &&
+- test -f conftest2.$ac_objext && { { case "(($ac_try" in
+- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+- *) ac_try_echo=$ac_try;;
+-esac
+-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+-$as_echo "$ac_try_echo"; } >&5
+- (eval "$ac_try") 2>&5
+- ac_status=$?
+- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+- test $ac_status = 0; };
+-then
+- eval ac_cv_prog_cc_${ac_cc}_c_o=yes
+- if test "x$CC" != xcc; then
+- # Test first that cc exists at all.
+- if { ac_try='cc -c conftest.$ac_ext >&5'
+- { { case "(($ac_try" in
+- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+- *) ac_try_echo=$ac_try;;
+-esac
+-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+-$as_echo "$ac_try_echo"; } >&5
+- (eval "$ac_try") 2>&5
+- ac_status=$?
+- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+- test $ac_status = 0; }; }; then
+- ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
+- rm -f conftest2.*
+- if { { case "(($ac_try" in
+- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+- *) ac_try_echo=$ac_try;;
+-esac
+-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+-$as_echo "$ac_try_echo"; } >&5
+- (eval "$ac_try") 2>&5
+- ac_status=$?
+- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+- test $ac_status = 0; } &&
+- test -f conftest2.$ac_objext && { { case "(($ac_try" in
+- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+- *) ac_try_echo=$ac_try;;
+-esac
+-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+-$as_echo "$ac_try_echo"; } >&5
+- (eval "$ac_try") 2>&5
+- ac_status=$?
+- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+- test $ac_status = 0; };
+- then
+- # cc works too.
+- :
+- else
+- # cc exists but doesn't like -o.
+- eval ac_cv_prog_cc_${ac_cc}_c_o=no
+- fi
+- fi
+- fi
+-else
+- eval ac_cv_prog_cc_${ac_cc}_c_o=no
+-fi
+-rm -f core conftest*
+-
+-fi
+-if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then
+- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+-$as_echo "yes" >&6; }
+-else
+- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-$as_echo "no" >&6; }
+-
+-$as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h
+-
+-fi
+-
+-# FIXME: we rely on the cache variable name because
+-# there is no other way.
+-set dummy $CC
+-am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
+-eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o
+-if test "$am_t" != yes; then
+- # Losing compiler, so override with the script.
+- # FIXME: It is wrong to rewrite CC.
+- # But if we don't then we get into trouble of one sort or another.
+- # A longer-term fix would be to have automake use am__CC in this case,
+- # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+- CC="$am_aux_dir/compile $CC"
+-fi
+-
+
+ case `pwd` in
+ *\ * | *\ *)
+@@ -16950,6 +16927,7 @@ fi
+ cat > local.exp <<EOF
+ set CC_FOR_TARGET "$CC"
+ set CXX_FOR_TARGET "$CXX"
++lappend boards_dir "$srcdir/../misc"
+ EOF
+
+
+@@ -17337,6 +17315,10 @@ case "$host" in
+ TARGET=POWERPC; TARGETDIR=powerpc
+ ;;
+
++ riscv | riscv-* | riscv64-*)
++ TARGET=RISCV; TARGETDIR=riscv;
++ ;;
++
+ s390-*-* | s390x-*-*)
+ TARGET=S390; TARGETDIR=s390
+ ;;
+@@ -17353,8 +17335,8 @@ case "$host" in
+ ;;
+
+ tile*-*)
+- TARGET=TILE; TARGETDIR=tile
+- ;;
++ TARGET=TILE; TARGETDIR=tile
++ ;;
+
+ vax-*-*)
+ TARGET=VAX; TARGETDIR=vax
+@@ -17373,6 +17355,14 @@ if test $TARGETDIR = unknown; then
+ as_fn_error $? "\"libffi has not been ported to $host.\"" "$LINENO" 5
+ fi
+
++ if test x$TARGET = xRISCV; then
++ RISCV_TRUE=
++ RISCV_FALSE='#'
++else
++ RISCV_TRUE='#'
++ RISCV_FALSE=
++fi
++
+ if test x$TARGET = xMIPS; then
+ MIPS_TRUE=
+ MIPS_FALSE='#'
+@@ -18963,6 +18953,10 @@ if test -z "${TESTSUBDIR_TRUE}" && test -z "${TESTSUBDIR_FALSE}"; then
+ as_fn_error $? "conditional \"TESTSUBDIR\" was never defined.
+ Usually this means the macro was only invoked conditionally." "$LINENO" 5
+ fi
++if test -z "${RISCV_TRUE}" && test -z "${RISCV_FALSE}"; then
++ as_fn_error $? "conditional \"RISCV\" was never defined.
++Usually this means the macro was only invoked conditionally." "$LINENO" 5
++fi
+ if test -z "${MIPS_TRUE}" && test -z "${MIPS_FALSE}"; then
+ as_fn_error $? "conditional \"MIPS\" was never defined.
+ Usually this means the macro was only invoked conditionally." "$LINENO" 5
+diff --git a/libffi-3.1/configure.ac b/libffi-3.1/configure.ac
index d3b8b99..9e4049c 100644
---- a/configure.ac
-+++ b/configure.ac
+--- a/libffi-3.1/configure.ac
++++ b/libffi-3.1/configure.ac
@@ -59,6 +59,7 @@ fi
cat > local.exp <<EOF
set CC_FOR_TARGET "$CC"
@@ -72,11 +1148,234 @@ index d3b8b99..9e4049c 100644
AM_CONDITIONAL(MIPS, test x$TARGET = xMIPS)
AM_CONDITIONAL(BFIN, test x$TARGET = xBFIN)
AM_CONDITIONAL(SPARC, test x$TARGET = xSPARC)
-diff --git a/src/riscv/asm.py b/src/riscv/asm.py
+diff --git a/libffi-3.1/fficonfig.h.in b/libffi-3.1/fficonfig.h.in
+index cdef91b..c5a784f 100644
+--- a/libffi-3.1/fficonfig.h.in
++++ b/libffi-3.1/fficonfig.h.in
+@@ -124,9 +124,6 @@
+ /* Define to the sub-directory where libtool stores uninstalled libraries. */
+ #undef LT_OBJDIR
+
+-/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+-#undef NO_MINUS_C_MINUS_O
+-
+ /* Name of package */
+ #undef PACKAGE
+
+diff --git a/libffi-3.1/include/Makefile.in b/libffi-3.1/include/Makefile.in
+index 9d747e8..61e41a7 100644
+--- a/libffi-3.1/include/Makefile.in
++++ b/libffi-3.1/include/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated by automake 1.13.4 from Makefile.am.
++# Makefile.in generated by automake 1.14.1 from Makefile.am.
+ # @configure_input@
+
+ # Copyright (C) 1994-2013 Free Software Foundation, Inc.
+diff --git a/libffi-3.1/man/Makefile.in b/libffi-3.1/man/Makefile.in
+index d92af74..47d6d8c 100644
+--- a/libffi-3.1/man/Makefile.in
++++ b/libffi-3.1/man/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated by automake 1.13.4 from Makefile.am.
++# Makefile.in generated by automake 1.14.1 from Makefile.am.
+ # @configure_input@
+
+ # Copyright (C) 1994-2013 Free Software Foundation, Inc.
+diff --git a/libffi-3.1/misc/riscv-sim.exp b/libffi-3.1/misc/riscv-sim.exp
new file mode 100644
-index 0000000..55c3c33
+index 0000000..03177d2
--- /dev/null
-+++ b/src/riscv/asm.py
++++ b/libffi-3.1/misc/riscv-sim.exp
+@@ -0,0 +1,6 @@
++load_generic_config "sim"
++set_board_info sim "spike pk"
++set_board_info compiler "[find_gcc]"
++set_board_info ldflags "-static"
++set_board_info gdb,nosignals 1
++set_board_info is_simulator 1
+diff --git a/libffi-3.1/misc/run_test.sh b/libffi-3.1/misc/run_test.sh
+new file mode 100755
+index 0000000..dcc0191
+--- /dev/null
++++ b/libffi-3.1/misc/run_test.sh
+@@ -0,0 +1,3 @@
++#/bin/bash
++riscv64-unknown-elf-gcc -I../../riscv64-unknown-elf/include -I../../riscv64-unknown-elf -L../../riscv64-unknown-elf/.libs/ $1 -lffi
++spike pk a.out
+diff --git a/libffi-3.1/src/riscv/.deps/.dirstamp b/libffi-3.1/src/riscv/.deps/.dirstamp
+new file mode 100644
+index 0000000..e69de29
+diff --git a/libffi-3.1/src/riscv/.deps/ffi.Plo b/libffi-3.1/src/riscv/.deps/ffi.Plo
+new file mode 100644
+index 0000000..eb18c9b
+--- /dev/null
++++ b/libffi-3.1/src/riscv/.deps/ffi.Plo
+@@ -0,0 +1,61 @@
++src/riscv/ffi.lo: src/riscv/ffi.c include/ffi.h include/ffitarget.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/include/stddef.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/include-fixed/limits.h \
++ include/ffi_common.h fficonfig.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/alloca.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/_ansi.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/newlib.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/sys/config.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/machine/ieeefp.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/sys/reent.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/_ansi.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/sys/_types.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/machine/_types.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/machine/_default_types.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/sys/lock.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/string.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/sys/string.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/stdlib.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/machine/stdlib.h
++
++include/ffi.h:
++
++include/ffitarget.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/include/stddef.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/include-fixed/limits.h:
++
++include/ffi_common.h:
++
++fficonfig.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/alloca.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/_ansi.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/newlib.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/sys/config.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/machine/ieeefp.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/sys/reent.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/_ansi.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/sys/_types.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/machine/_types.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/machine/_default_types.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/sys/lock.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/string.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/sys/string.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/stdlib.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/machine/stdlib.h:
+diff --git a/libffi-3.1/src/riscv/.deps/ffi64.Plo b/libffi-3.1/src/riscv/.deps/ffi64.Plo
+new file mode 100644
+index 0000000..e765ffb
+--- /dev/null
++++ b/libffi-3.1/src/riscv/.deps/ffi64.Plo
+@@ -0,0 +1,61 @@
++src/riscv/ffi64.lo: src/riscv/ffi64.c include/ffi.h include/ffitarget.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/include/stddef.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/include-fixed/limits.h \
++ include/ffi_common.h fficonfig.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/alloca.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/_ansi.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/newlib.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/sys/config.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/machine/ieeefp.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/sys/reent.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/_ansi.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/sys/_types.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/machine/_types.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/machine/_default_types.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/sys/lock.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/string.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/sys/string.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/stdlib.h \
++ /home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/machine/stdlib.h
++
++include/ffi.h:
++
++include/ffitarget.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/include/stddef.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/include-fixed/limits.h:
++
++include/ffi_common.h:
++
++fficonfig.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/alloca.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/_ansi.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/newlib.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/sys/config.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/machine/ieeefp.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/sys/reent.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/_ansi.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/sys/_types.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/machine/_types.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/machine/_default_types.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/sys/lock.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/string.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/sys/string.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/stdlib.h:
++
++/home/risc-v/riscv/lib64/gcc/riscv-elf/4.6.1/../../../../riscv-elf/include/machine/stdlib.h:
+diff --git a/libffi-3.1/src/riscv/.deps/rv32.Plo b/libffi-3.1/src/riscv/.deps/rv32.Plo
+new file mode 100644
+index 0000000..ffad3c5
+--- /dev/null
++++ b/libffi-3.1/src/riscv/.deps/rv32.Plo
+@@ -0,0 +1,8 @@
++src/riscv/rv32.lo: src/riscv/rv32.S fficonfig.h include/ffi.h \
++ include/ffitarget.h
++
++fficonfig.h:
++
++include/ffi.h:
++
++include/ffitarget.h:
+diff --git a/libffi-3.1/src/riscv/.deps/rv64.Plo b/libffi-3.1/src/riscv/.deps/rv64.Plo
+new file mode 100644
+index 0000000..439907d
+--- /dev/null
++++ b/libffi-3.1/src/riscv/.deps/rv64.Plo
+@@ -0,0 +1,8 @@
++src/riscv/rv64.lo: src/riscv/rv64.S fficonfig.h include/ffi.h \
++ include/ffitarget.h
++
++fficonfig.h:
++
++include/ffi.h:
++
++include/ffitarget.h:
+diff --git a/libffi-3.1/src/riscv/.dirstamp b/libffi-3.1/src/riscv/.dirstamp
+new file mode 100644
+index 0000000..e69de29
+diff --git a/libffi-3.1/src/riscv/asm.py b/libffi-3.1/src/riscv/asm.py
+new file mode 100644
+index 0000000..0d6ab2c
+--- /dev/null
++++ b/libffi-3.1/src/riscv/asm.py
@@ -0,0 +1,37 @@
+#!/bin/python
+
@@ -92,7 +1391,7 @@ index 0000000..55c3c33
+
+ # when its zero, it means its just a word-sized int/ptr
+ bne t1, zero, set_arg""" + str(i) + """_float
-+ ld a""" + str(i) + """, FFI_SIZEOF_ARG_X""" + str(i) + """(sp) # load argument
++ REG_L a""" + str(i) + """, FFI_SIZEOF_ARG_X""" + str(i) + """(sp) # load argument
+ j set_arg""" + str(i+1) + """
+
+set_arg""" + str(i) + """_float:
@@ -115,13 +1414,12 @@ index 0000000..55c3c33
+ return setargs
+
+print gen64_setargs_string()
-\ No newline at end of file
-diff --git a/src/riscv/ffi.c b/src/riscv/ffi.c
+diff --git a/libffi-3.1/src/riscv/ffi.c b/libffi-3.1/src/riscv/ffi.c
new file mode 100644
-index 0000000..9e130a2
+index 0000000..54961ad
--- /dev/null
-+++ b/src/riscv/ffi.c
-@@ -0,0 +1,327 @@
++++ b/libffi-3.1/src/riscv/ffi.c
+@@ -0,0 +1,654 @@
+/* -----------------------------------------------------------------------
+ ffi.c - 2014 Michael Knyszek
+
@@ -152,6 +1450,7 @@ index 0000000..9e130a2
+#include <ffi_common.h>
+
+#include <stdlib.h>
++#include <stdint.h>
+
+/* ffi_prep_args is called by the assembly routine once stack space
+ has been allocated for the function's arguments */
@@ -162,7 +1461,11 @@ index 0000000..9e130a2
+ void **p_argv;
+ char *argp;
+ ffi_type **p_arg;
-+ argp = stack;
++
++ if (bytes > 8 * sizeof(ffi_arg))
++ argp = &stack[bytes - (8 * sizeof(ffi_arg))];
++ else
++ argp = stack;
+
+ memset(stack, 0, bytes);
+
@@ -252,15 +1555,12 @@ index 0000000..9e130a2
+ *(ffi_arg *)argp = *(UINT64 *)(* p_argv);
+ break;
+
++ /* This can only happen with 64bit slots. */
+ case FFI_TYPE_FLOAT:
+ *(float *) argp = *(float *)(* p_argv);
+ break;
-+
-+ case FFI_TYPE_DOUBLE:
-+ *(double *) argp = *(double *)(* p_argv);
-+ break;
+
-+ /* Handle structures. */
++ /* Handle structures. */
+ default:
+ memcpy(argp, *p_argv, (*p_arg)->size);
+ break;
@@ -268,7 +1568,23 @@ index 0000000..9e130a2
+ }
+ else
+ {
-+ memcpy(argp, *p_argv, z);
++ unsigned long end = (unsigned long) argp + z;
++ unsigned long cap = (unsigned long) stack + bytes;
++
++ /* Check if the data will fit within the register space.
++ Handle it if it doesn't. */
++
++ if (end <= cap)
++ memcpy(argp, *p_argv, z);
++ else
++ {
++ unsigned long portion = cap - (unsigned long)argp;
++
++ memcpy(argp, *p_argv, portion);
++ argp = stack;
++ z -= portion;
++ memcpy(argp, (void*)((unsigned long)(*p_argv) + portion), z);
++ }
+ }
+
+ p_argv++;
@@ -276,19 +1592,133 @@ index 0000000..9e130a2
+ }
+}
+
++/* This code traverses structure definitions
++ and generates the appropriate flags. */
++
++static unsigned calc_riscv_struct_flags(int soft_float, ffi_type *arg, unsigned *loc, unsigned *arg_reg)
++{
++ unsigned flags = 0;
++ unsigned index = 0;
++ ffi_type *e;
++
++ if (soft_float)
++ return 0;
++
++ while ((e = arg->elements[index]))
++ {
++ /* Align this object. */
++ *loc = ALIGN(*loc, e->alignment);
++
++ if (e->type == FFI_TYPE_DOUBLE)
++ {
++ /* Already aligned to FFI_SIZEOF_ARG. */
++ *arg_reg = *loc / FFI_SIZEOF_ARG;
++
++ if (*arg_reg > 7)
++ break;
++
++ flags += (FFI_TYPE_DOUBLE << (*arg_reg * FFI_FLAG_BITS));
++ *loc += e->size;
++ }
++ else
++ *loc += e->size;
++
++ index++;
++ }
++
++ /* Next Argument register at alignment of FFI_SIZEOF_ARG. */
++ *arg_reg = ALIGN(*loc, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
++
++ return flags;
++}
++
++static unsigned calc_riscv_return_struct_flags(int soft_float, ffi_type *arg)
++{
++ unsigned flags = 0;
++ unsigned small = FFI_TYPE_SMALLSTRUCT;
++ ffi_type *e;
++
++ /* Returning structures under n32 is a tricky thing.
++ A struct with only one or two floating point fields
++ is returned in $f0 (and $f2 if necessary). Any other
++ struct results at most 128 bits are returned in $2
++ (the first 64 bits) and $3 (remainder, if necessary).
++ Larger structs are handled normally. */
++
++ if (arg->size > 2 * FFI_SIZEOF_ARG)
++ return 0;
++
++ if (arg->size > 8)
++ small = FFI_TYPE_SMALLSTRUCT2;
++
++ e = arg->elements[0];
++ if (e->type == FFI_TYPE_DOUBLE)
++ flags = FFI_TYPE_DOUBLE;
++ else if (e->type == FFI_TYPE_FLOAT)
++ flags = FFI_TYPE_FLOAT;
++
++ if (flags && (e = arg->elements[1]))
++ {
++ if (e->type == FFI_TYPE_DOUBLE)
++ flags += FFI_TYPE_DOUBLE << FFI_FLAG_BITS;
++ else if (e->type == FFI_TYPE_FLOAT)
++ flags += FFI_TYPE_FLOAT << FFI_FLAG_BITS;
++ else
++ return small;
++
++ if (flags && (arg->elements[2]))
++ {
++ /* There are three arguments and the first two are
++ floats! This must be passed the old way. */
++ return small;
++ }
++
++ if (soft_float)
++ flags += FFI_TYPE_STRUCT_SOFT;
++ }
++ else if (!flags)
++ return small;
++
++ return flags;
++}
++
+/* Perform machine dependent cif processing */
+
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
-+ int i;
-+ unsigned int prev_dbl_size = 0;
++ int type;
++ unsigned arg_reg = 0;
++ unsigned loc = 0;
++ unsigned count = (cif->nargs < 8) ? cif->nargs : 8;
++ unsigned index = 0;
++
++ unsigned int struct_flags = 0;
++ int soft_float = cif->abi == FFI_RV64_SOFT_FLOAT || cif->abi == FFI_RV32_SOFT_FLOAT;;
++
+ cif->flags = 0;
+
++ if (cif->rtype->type == FFI_TYPE_STRUCT)
++ {
++ struct_flags = calc_riscv_return_struct_flags(soft_float, cif->rtype);
++ if (struct_flags == 0)
++ {
++ /* This means that the structure is being passed as
++ a hidden argument */
++ arg_reg = 1;
++ count = (cif->nargs < 7) ? cif->nargs : 7;
++ cif->rstruct_flag = !0;
++ }
++ else
++ cif->rstruct_flag = 0;
++ }
++ else
++ cif->rstruct_flag = 0;
++
+ /* Set the first 8 existing argument types in the flag bit string
+ *
+ * We only describe the two argument types we care about:
-+ * - Whether or not its a float
-+ * - Whether or not its a 64 bit type
++ * - Whether or not its a float/double
++ * - Whether or not its a struct
+ *
+ * This is is two bits per argument accounting for the first 16 bits
+ * of cif->flags.
@@ -298,126 +1728,101 @@ index 0000000..9e130a2
+ * FFI_FLAG_BITS = 2
+ */
+
-+ for(i = 0; i < cif->nargs && i < 8; ++i)
++ while (count-- > 0 && arg_reg < 8)
+ {
-+ #ifdef __riscv64
-+ switch ((cif->arg_types)[i]->type)
++ type = (cif->arg_types)[index]->type;
++
++ /* Handle float argument types for soft float case */
++ if (soft_float)
+ {
-+ case FFI_TYPE_FLOAT:
-+ cif->flags += 1 << (FFI_FLAG_BITS * i);
-+
-+ prev_dbl_size = 0;
-+ break;
-+
-+ case FFI_TYPE_DOUBLE:
-+ cif->flags += 2 << (FFI_FLAG_BITS * i);
-+
-+ prev_dbl_size = 0;
-+ break;
-+
-+ /*case FFI_TYPE_LONG_DOUBLE:
-+ if (i == 7) break;
-+ if (!prev_dbl_size && i % 2 != 0) ++i;
-+
-+ cif->flags += 3 << (FFI_FLAG_BITS * i);
-+
-+ ++i;
-+ prev_dbl_size = 1;
-+ break;
-+ */
-+ default:
-+ prev_dbl_size = 0;
-+ break;
++ switch (type)
++ {
++ case FFI_TYPE_FLOAT:
++ type = FFI_TYPE_UINT32;
++ break;
++ case FFI_TYPE_DOUBLE:
++ type = FFI_TYPE_UINT64;
++ break;
++ default:
++ break;
++ }
+ }
-+ #else
-+ switch ((cif->arg_types)[i]->type)
++ switch (type)
+ {
+ case FFI_TYPE_FLOAT:
-+ cif->flags += 1 << (FFI_FLAG_BITS * i);
-+
-+ prev_dbl_size = 0;
-+ break;
-+
+ case FFI_TYPE_DOUBLE:
-+ if (i == 7) break;
-+ if (!prev_dbl_size && i % 2 != 0) ++i;
-+
-+ cif->flags += 3 << (FFI_FLAG_BITS * i);
-+ ++i;
-+
-+ prev_dbl_size = 1;
++ cif->flags += ((cif->arg_types)[index]->type << (arg_reg * FFI_FLAG_BITS));
++ arg_reg++;
+ break;
-+
-+ case FFI_TYPE_SINT64:
-+ case FFI_TYPE_UINT64:
-+ if (i == 7) break;
-+ if (!prev_dbl_size && i % 2 != 0) ++i;
-+
-+ cif->flags += 2 << (FFI_FLAG_BITS * i);
-+ ++i;
-+
-+ prev_dbl_size = 1;
++ case FFI_TYPE_STRUCT:
++ loc = arg_reg * FFI_SIZEOF_ARG;
++ cif->flags += calc_riscv_struct_flags(soft_float, (cif->arg_types)[index], &loc, &arg_reg);
+ break;
-+
+ default:
-+ prev_dbl_size = 0;
++ arg_reg++;
+ break;
+ }
-+ #endif
++ index++;
+ }
-+
++
+ /* Set the return type flag */
-+
-+ if (cif->abi == FFI_RV32_SOFT_FLOAT || cif->abi == FFI_RV64_SOFT_FLOAT)
++
++ type = cif->rtype->type;
++
++ /* Handle float return types for soft float case */
++ if (soft_float)
+ {
-+ switch (cif->rtype->type)
++ switch (type)
+ {
-+ // long long is the same size as a word in riscv64
-+ #ifndef __riscv64
-+ case FFI_TYPE_SINT64:
-+ case FFI_TYPE_UINT64:
++ case FFI_TYPE_FLOAT:
++ type = FFI_TYPE_UINT32;
++ break;
+ case FFI_TYPE_DOUBLE:
-+ cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 8);
++ type = FFI_TYPE_UINT64;
+ break;
-+ #endif
+ default:
-+ cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
+ break;
+ }
+ }
-+ else
-+ {
-+ switch (cif->rtype->type)
-+ {
-+ case FFI_TYPE_FLOAT:
-+ case FFI_TYPE_DOUBLE:
-+ cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
-+ break;
-+ // long long is the same size as a word in riscv64
++
++ switch (type)
++ {
++ case FFI_TYPE_STRUCT:
++ if (struct_flags != 0)
++ {
++ /* The structure is returned via some tricky mechanism */
++ cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
++ cif->flags += struct_flags << (4 + (FFI_FLAG_BITS * 8));
++ }
++ /* else the structure is returned through a hidden
++ first argument. Do nothing, 'cause FFI_TYPE_VOID is 0 */
++ break;
++ case FFI_TYPE_VOID:
++ /* Do nothing, 'cause FFI_TYPE_VOID is 0 */
++ break;
++ case FFI_TYPE_FLOAT:
++ case FFI_TYPE_DOUBLE:
++ cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
++ break;
+ #ifndef __riscv64
-+ case FFI_TYPE_SINT64:
-+ case FFI_TYPE_UINT64:
-+ cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 8);
-+ break;
++ case FFI_TYPE_SINT64:
++ case FFI_TYPE_UINT64:
++ cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 8);
++ break;
+ #endif
-+ default:
-+ cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
-+ break;
-+ }
++ default:
++ cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
++ break;
+ }
+
+ return FFI_OK;
+}
+
-+/* Low level routine for calling RV32 functions */
-+extern int ffi_call_rv32(void (*)(char *, extended_cif *, int, int),
-+ extended_cif *, unsigned, unsigned,
-+ unsigned *, void (*)(void));
-+
+/* Low level routine for calling RV64 functions */
-+extern int ffi_call_rv64(void (*)(char *, extended_cif *, int, int),
++extern int ffi_call_asm(void (*)(char *, extended_cif *, int, int),
+ extended_cif *, unsigned, unsigned,
-+ unsigned *, void (*)(void));
++ unsigned *, void (*)(void))
++ __attribute__((visibility("hidden")));
+
+void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
@@ -427,145 +1832,254 @@ index 0000000..9e130a2
+ ecif.avalue = avalue;
+
+ /* If the return value is a struct and we don't have a return */
-+ /* value address then we need to make one */
++ /* value address then we need to make one */
+
+ if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
+ ecif.rvalue = alloca(cif->rtype->size);
+ else
+ ecif.rvalue = rvalue;
+
-+ switch (cif->abi)
++ int copy_rvalue = 0;
++ char *rvalue_copy = ecif.rvalue;
++ if (cif->rtype->type == FFI_TYPE_STRUCT && cif->rtype->size < 2 * FFI_SIZEOF_ARG)
+ {
-+ case FFI_RV32:
-+ case FFI_RV32_SOFT_FLOAT:
-+ ffi_call_rv32(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, fn);
-+ break;
-+ case FFI_RV64:
-+ case FFI_RV64_SOFT_FLOAT:
-+ ffi_call_rv64(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, fn);
-+ break;
-+ default:
-+ FFI_ASSERT(0);
-+ break;
++ /* For structures smaller than 16 bytes we clobber memory
++ in 8 byte increments. Make a copy so we don't clobber
++ the callers memory outside of the struct bounds. */
++ rvalue_copy = alloca(2 * FFI_SIZEOF_ARG);
++ copy_rvalue = 1;
+ }
++ else if (cif->rtype->type == FFI_TYPE_FLOAT && (cif->abi == FFI_RV64_SOFT_FLOAT || cif->abi == FFI_RV32_SOFT_FLOAT))
++ {
++ rvalue_copy = alloca(FFI_SIZEOF_ARG);
++ copy_rvalue = 1;
++ }
++
++ ffi_call_asm(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, fn);
++
++ if (copy_rvalue)
++ memcpy(ecif.rvalue, rvalue_copy, cif->rtype->size);
+}
-diff --git a/src/riscv/ffi64.c b/src/riscv/ffi64.c
-new file mode 100644
-index 0000000..f0d45eb
---- /dev/null
-+++ b/src/riscv/ffi64.c
-@@ -0,0 +1,105 @@
-+/* -----------------------------------------------------------------------
-+ ffi64.c - 2014 Michael Knyszek
-+
-+ RISC-V 64-bit Foreign Function Interface
-+
-+ Permission is hereby granted, free of charge, to any person obtaining
-+ a copy of this software and associated documentation files (the
-+ ``Software''), to deal in the Software without restriction, including
-+ without limitation the rights to use, copy, modify, merge, publish,
-+ distribute, sublicense, and/or sell copies of the Software, and to
-+ permit persons to whom the Software is furnished to do so, subject to
-+ the following conditions:
-+
-+ The above copyright notice and this permission notice shall be included
-+ in all copies or substantial portions of the Software.
-+
-+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-+ DEALINGS IN THE SOFTWARE.
-+ ----------------------------------------------------------------------- */
+
-+#include <ffi.h>
-+#include <ffi_common.h>
++#if FFI_CLOSURES
+
-+#include <stdlib.h>
++extern void ffi_closure_asm(void) __attribute__((visibility("hidden")));
+
-+/* Perform machine dependent cif processing */
-+
-+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
++ffi_status ffi_prep_closure_loc(ffi_closure *closure, ffi_cif *cif, void (*fun)(ffi_cif*,void*,void**,void*), void *user_data, void *codeloc)
+{
-+ int i;
-+ unsigned int prev_dbl_size = 0;
-+ cif->flags = 0;
++ unsigned int *tramp = (unsigned int *) &closure->tramp[0];
+
-+ /* Set the first 8 existing argument types in the flag bit string
-+ *
-+ * We only describe the two argument types we care about:
-+ * - Whether or not its a float
-+ * - Whether or not its a 128 bit type (only long double)
-+ *
-+ * This is is two bits per argument accounting for the first 16 bits
-+ * of cif->flags.
-+ *
-+ * The last 16 bits are just used to describe the return type
-+ *
-+ * FFI_FLAG_BITS = 2
-+ */
++ uintptr_t fn = (uintptr_t) ffi_closure_asm;
++ FFI_ASSERT(tramp == codeloc);
++
++ /* Remove when more than just rv64 is supported */
++ if (cif->abi != FFI_RV64)
++ return FFI_BAD_ABI;
+
-+ for(i = 0; i < cif->nargs && i < 8; ++i)
++ if (cif->abi == FFI_RV32 || cif->abi == FFI_RV32_SOFT_FLOAT || fn < 0x7ffff000U)
+ {
-+
++ /* auipc t0, 0 (i.e. t0 <- codeloc) */
++ tramp[0] = 0x00000297;
++ /* lui t1, %hi(fn) */
++ tramp[1] = 0x00000337 | ((fn + 0x800) & 0xFFFFF000);
++ /* jalr x0, t1, %lo(fn) */
++ tramp[2] = 0x00030067 | ((fn & 0xFFF) << 20);
++ /* nops */
++ tramp[3] = 0x00000013;
++ tramp[4] = 0x00000013;
++ tramp[5] = 0x00000013;
+ }
++ else
++ {
++ /* auipc t0, 0 (i.e. t0 <- codeloc) */
++ tramp[0] = 0x00000297;
++ /* ld t1, 16(t0) */
++ tramp[1] = 0x0102b303;
++ /* jalr x0, t1, %lo(fn) */
++ tramp[2] = 0x00030067;
++ /* nop */
++ tramp[3] = 0x00000013;
++ /* fn */
++ tramp[4] = fn;
++ tramp[5] = fn >> 32;
++ }
++
++ closure->cif = cif;
++ closure->fun = fun;
++ closure->user_data = user_data;
++ __builtin___clear_cache(codeloc, codeloc + FFI_TRAMPOLINE_SIZE);
++
++ return FFI_OK;
++}
+
-+ /* Set the return type flag */
++static void copy_struct(char *target, unsigned offset, ffi_abi abi, ffi_type *type, int argn, unsigned arg_offset, ffi_arg *ar, ffi_arg *fpr, int soft_float)
++{
++ ffi_type **elt_typep = type->elements;
++
++ while(*elt_typep)
++ {
++ ffi_type *elt_type = *elt_typep;
++ unsigned o;
++ char *tp;
++ char *argp;
++ char *fpp;
++
++ o = ALIGN(offset, elt_type->alignment);
++ arg_offset += o - offset;
++ offset = o;
++ argn += arg_offset / sizeof(ffi_arg);
++ arg_offset = arg_offset % sizeof(ffi_arg);
++ argp = (char *)(ar + argn);
++ fpp = (char *)(argn >= 8 ? ar + argn : fpr + argn);
++ tp = target + offset;
++
++ if (elt_type->type == FFI_TYPE_DOUBLE && !soft_float)
++ *(double *)tp = *(double *)fpp;
++ else
++ memcpy(tp, argp + arg_offset, elt_type->size);
++
++ offset += elt_type->size;
++ arg_offset += elt_type->size;
++ elt_typep++;
++ argn += arg_offset / sizeof(ffi_arg);
++ arg_offset = arg_offset % sizeof(ffi_arg);
++ }
++}
+
-+ if (cif->abi == FFI_RV64_SOFT_FLOAT)
++/*
++* Decodes the arguments to a function, which will be stored on the
++* stack. AR is the pointer to the beginning of the integer
++* arguments. FPR is a pointer to the area where floating point
++* registers have been saved.
++*
++* RVALUE is the location where the function return value will be
++* stored. CLOSURE is the prepared closure to invoke.
++*
++* This function should only be called from assembly, which is in
++* turn called from a trampoline.
++*
++* Returns the function return flags.
++*
++*/
++int ffi_closure_riscv_inner(ffi_closure *closure, void *rvalue, ffi_arg *ar, ffi_arg *fpr)
++{
++ ffi_cif *cif;
++ void **avaluep;
++ ffi_arg *avalue;
++ ffi_type **arg_types;
++ int i, avn, argn;
++ int soft_float;
++ ffi_arg *argp;
++
++ cif = closure->cif;
++ soft_float = cif->abi == FFI_RV64_SOFT_FLOAT || cif->abi == FFI_RV32_SOFT_FLOAT;
++ avalue = alloca(cif->nargs * sizeof (ffi_arg));
++ avaluep = alloca(cif->nargs * sizeof (ffi_arg));
++ argn = 0;
++
++ if (cif->rstruct_flag)
++ {
++ rvalue = (void *)ar[0];
++ argn = 1;
++ }
++
++ i = 0;
++ avn = cif->nargs;
++ arg_types = cif->arg_types;
++
++ while (i < avn)
+ {
-+ switch (cif->rtype->type)
++ if (arg_types[i]->type == FFI_TYPE_FLOAT || arg_types[i]->type == FFI_TYPE_DOUBLE || arg_types[i]->type == FFI_TYPE_LONGDOUBLE)
+ {
-+ case FFI_TYPE_VOID:
-+ case FFI_TYPE_POINTER:
-+ case FFI_TYPE_STRUCT:
-+ //case FFI_TYPE_LONG_DOUBLE:
-+ cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
-+ break;
-+ case FFI_TYPE_SINT64:
-+ case FFI_TYPE_UINT64:
-+ case FFI_TYPE_DOUBLE:
-+ cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 8);
-+ break;
-+ case FFI_TYPE_FLOAT:
-+ default:
-+ cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
-+ break;
++ argp = (argn >= 8 || soft_float) ? ar + argn : fpr + argn;
++ if ((arg_types[i]->type == FFI_TYPE_LONGDOUBLE) && ((uintptr_t)argp & (arg_types[i]->alignment-1)))
++ {
++ argp=(ffi_arg*)ALIGN(argp,arg_types[i]->alignment);
++ argn++;
++ }
++ avaluep[i] = (char *) argp;
+ }
-+ }
-+ else
-+ {
-+ switch (cif->rtype->type)
++ else
+ {
-+ case FFI_TYPE_VOID:
-+ case FFI_TYPE_POINTER:
-+ case FFI_TYPE_STRUCT:
-+ case FFI_TYPE_FLOAT:
-+ case FFI_TYPE_DOUBLE:
-+ //case FFI_TYPE_LONG_DOUBLE:
-+ cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
-+ break;
-+ case FFI_TYPE_SINT64:
-+ case FFI_TYPE_UINT64:
-+ cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 8);
-+ break;
-+ default:
-+ cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
-+ break;
++ unsigned type = arg_types[i]->type;
++
++ if (arg_types[i]->alignment > sizeof(ffi_arg))
++ argn = ALIGN(argn, arg_types[i]->alignment / sizeof(ffi_arg));
++
++ argp = ar + argn;
++
++ /* The size of a pointer depends on the ABI */
++ if (type == FFI_TYPE_POINTER)
++ type = (cif->abi == FFI_RV64 || cif->abi == FFI_RV64_SOFT_FLOAT) ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
++ if (soft_float && type == FFI_TYPE_FLOAT)
++ type = FFI_TYPE_UINT32;
++
++ switch (type)
++ {
++ case FFI_TYPE_SINT8:
++ avaluep[i] = &avalue[i];
++ *(SINT8 *) &avalue[i] = (SINT8) *argp;
++ break;
++
++ case FFI_TYPE_UINT8:
++ avaluep[i] = &avalue[i];
++ *(UINT8 *) &avalue[i] = (UINT8) *argp;
++ break;
++
++ case FFI_TYPE_SINT16:
++ avaluep[i] = &avalue[i];
++ *(SINT16 *) &avalue[i] = (SINT16) *argp;
++ break;
++
++ case FFI_TYPE_UINT16:
++ avaluep[i] = &avalue[i];
++ *(UINT16 *) &avalue[i] = (UINT16) *argp;
++ break;
++
++ case FFI_TYPE_SINT32:
++ avaluep[i] = &avalue[i];
++ *(SINT32 *) &avalue[i] = (SINT32) *argp;
++ break;
++
++ case FFI_TYPE_UINT32:
++ avaluep[i] = &avalue[i];
++ *(UINT32 *) &avalue[i] = (UINT32) *argp;
++ break;
++
++ case FFI_TYPE_STRUCT:
++ if (argn < 8)
++ {
++ /* Allocate space for the struct as at least part of
++ it was passed in registers. */
++ avaluep[i] = alloca(arg_types[i]->size);
++ copy_struct(avaluep[i], 0, cif->abi, arg_types[i],
++ argn, 0, ar, fpr, soft_float);
++ break;
++ }
++
++ /* Else fall through. */
++ default:
++ avaluep[i] = (char *) argp;
++ break;
++ }
+ }
++
++ argn += ALIGN(arg_types[i]->size, sizeof(ffi_arg)) / sizeof(ffi_arg);
++ i++;
+ }
-+
-+ return FFI_OK;
++
++ /* Invoke the closure. */
++ (closure->fun) (cif, rvalue, avaluep, closure->user_data);
++ return cif->flags >> (FFI_FLAG_BITS * 8);
+}
-diff --git a/src/riscv/ffitarget.h b/src/riscv/ffitarget.h
++
++#endif /* FFI_CLOSURES */
+diff --git a/libffi-3.1/src/riscv/ffitarget.h b/libffi-3.1/src/riscv/ffitarget.h
new file mode 100644
-index 0000000..d56eb59
+index 0000000..b2b773b
--- /dev/null
-+++ b/src/riscv/ffitarget.h
-@@ -0,0 +1,74 @@
++++ b/libffi-3.1/src/riscv/ffitarget.h
+@@ -0,0 +1,119 @@
+/* -----------------------------------------------------------------*-C-*-
+ ffitarget.h - 2014 Michael Knyszek
+
@@ -600,10 +2114,20 @@ index 0000000..d56eb59
+#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead."
+#endif
+
-+#ifndef LIBFFI_ASM
++#ifndef __riscv64
++# error We currently only support RV64.
++#endif
++
++#ifdef __LP64__
++# define FFI_SIZEOF_ARG 8
++#else
++# define FFI_SIZEOF_ARG 4
++#endif
+
+#define FFI_FLAG_BITS 2
+
++#ifndef LIBFFI_ASM
++
+typedef unsigned long ffi_arg;
+typedef signed long ffi_sarg;
+
@@ -630,582 +2154,57 @@ index 0000000..d56eb59
+#endif /* __riscv_soft_float */
+} ffi_abi;
+
-+#endif /* LIBFFI_ASM */
-+
-+/* ---- Definitions for closures ----------------------------------------- */
-+
-+#define FFI_CLOSURES 0
-+#define FFI_TRAMPOLINE_SIZE 48
-+#define FFI_NATIVE_RAW_API 0
-+
-+#endif
-+
-diff --git a/src/riscv/rv32.S b/src/riscv/rv32.S
-new file mode 100644
-index 0000000..c31c439
---- /dev/null
-+++ b/src/riscv/rv32.S
-@@ -0,0 +1,554 @@
-+/* -----------------------------------------------------------------------
-+ rv32.S - Michael Knyszek 2014
-+
-+ RISC-V Foreign Function Interface
-+
-+ Permission is hereby granted, free of charge, to any person obtaining
-+ a copy of this software and associated documentation files (the
-+ ``Software''), to deal in the Software without restriction, including
-+ without limitation the rights to use, copy, modify, merge, publish,
-+ distribute, sublicense, and/or sell copies of the Software, and to
-+ permit persons to whom the Software is furnished to do so, subject to
-+ the following conditions:
-+
-+ The above copyright notice and this permission notice shall be included
-+ in all copies or substantial portions of the Software.
-+
-+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-+ DEALINGS IN THE SOFTWARE.
-+ ----------------------------------------------------------------------- */
-+
-+#define LIBFFI_ASM
-+#include <fficonfig.h>
-+#include <ffi.h>
-+
-+#define callback a0
-+#define ecif a1
-+#define bytes a2
-+#define flags a3
-+#define rvalue a4
-+#define fn a5
-+#define fp s0
-+
-+# The RISCV GCC compiler can't handle expressions in assembly, so
-+# the workaround is this:
-+
-+#define FFI_SIZEOF_ARG_X0 0
-+#define FFI_SIZEOF_ARG_X1 4
-+#define FFI_SIZEOF_ARG_X2 8
-+#define FFI_SIZEOF_ARG_X3 12
-+#define FFI_SIZEOF_ARG_X4 16
-+#define FFI_SIZEOF_ARG_X5 20
-+#define FFI_SIZEOF_ARG_X6 24
-+#define FFI_SIZEOF_ARG_X7 28
-+#define FFI_SIZEOF_ARG_X8 32
-+
-+#define ARG_MASK 65535
-+
-+#define FFI_FLAG_BITS_X0 0
-+#define FFI_FLAG_BITS_X1 2
-+#define FFI_FLAG_BITS_X2 4
-+#define FFI_FLAG_BITS_X3 6
-+#define FFI_FLAG_BITS_X4 8
-+#define FFI_FLAG_BITS_X5 10
-+#define FFI_FLAG_BITS_X6 12
-+#define FFI_FLAG_BITS_X7 14
-+
-+# Stack pointer needs to be 16-byte aligned, so frame size is rounded up
-+# FFI_SIZEOF_ARG should be 4 in the 32-bit case
-+
-+ .text
-+ .align 2
-+ .globl ffi_call_rv32
-+ .type ffi_call_rv32, @function
-+ffi_call_rv32:
-+ ### Prologue
-+
-+ # a0 - ffi_prep_args pointer
-+ # a1 - extended_cif pointer
-+ # a2 - bytes
-+ # a3 - flags
-+ # a4 - rvalue
-+ # a5 - function ptr
-+
-+ add sp, sp, -FFI_SIZEOF_ARG_X8 # move stack pointer by frame size
-+ # must be 16-byte aligned
-+
-+ # stack ptr points to first argument on stack,
-+ # but there should be no arguments on the stack
-+
-+ sw flags, FFI_SIZEOF_ARG_X0(sp) # save flags
-+ sw rvalue, FFI_SIZEOF_ARG_X1(sp) # save return value pointer
-+ sw fn, FFI_SIZEOF_ARG_X2(sp) # save function pointer
-+ sw fp, FFI_SIZEOF_ARG_X3(sp) # save frame pointer
-+ sw ra, FFI_SIZEOF_ARG_X4(sp) # save return address
-+
-+ add fp, sp, zero # new frame pointer is updated stack pointer
-+ add t4, callback, zero # function ptr to prep_args
-+
-+ # Allocate at least 8 words on the argstack
-+ ori t0, zero, FFI_SIZEOF_ARG_X8
-+ bltu bytes, t0, thirtytwo
-+
-+ # Here it turns out that our total arg space is bigger than our
-+ # argument register space, so we set it according to bytes
-+ # and makes sure its aligned to 16 bytes
-+
-+ add t0, bytes, 15 # make sure it is aligned
-+ andi t0, t0, -16 # to a 16 byte boundry
-+
-+thirtytwo:
-+ sub sp, sp, t0 # move the stack pointer to reflect the arg space
-+
-+ # a0 is the stack with proper arg space allocated
-+ add a0, sp, zero
-+
-+ # a1 is ecif
-+ # a2 is bytes
-+ # a3 is flags
-+
-+ jalr t4 # call ffi_prep_args
-+
-+ lw t0, 0(fp) # load the flags word
-+ srli t2, t0, 16 # shift our return type into t4
-+
-+ li t1, ARG_MASK
-+ and t0, t0, t1 # mask out the arg types into t0
-+
-+ # time to load the arguments for the call
-+
-+#ifndef __riscv_soft_float
-+
-+####################
-+## SET ARGUMENT 0 ##
-+####################
-+
-+set_arg0:
-+ srli t1, t0, FFI_FLAG_BITS_X0 # Shift to get the bits for this argument
-+ andi t1, t1, 3 # Mask out the bits for this argument
-+
-+ # when its zero, it means its just a word-sized int/ptr
-+ bne t1, zero, set_arg0_float
-+ lw a0, FFI_SIZEOF_ARG_X0(sp) # load argument
-+ j set_arg1
-+
-+set_arg0_float:
-+ addi t1, t1, -1
-+
-+ # when its zero, it means its just a word-sized float
-+ bne t1, zero, set_arg0_longlong
-+ flw fa0, FFI_SIZEOF_ARG_X0(sp) # load argument
-+ j set_arg1
-+
-+set_arg0_longlong:
-+ addi t1, t1, -1
-+
-+ # when its zero, it means its just a double-word-sized int/struct
-+ bne t1, zero, set_arg0_double
-+ lw a0, FFI_SIZEOF_ARG_X0(sp) # load low order bits into even
-+ lw a1, FFI_SIZEOF_ARG_X1(sp) # load high order bits into odd
-+ j set_arg2
-+
-+set_arg0_double:
-+ # otherwise it must be a double we're dealing with
-+ flw fa0, FFI_SIZEOF_ARG_X0(sp) # load low order bits into even
-+ flw fa1, FFI_SIZEOF_ARG_X1(sp) # load high order bits into odd
-+ j set_arg2
-+
-+####################
-+## SET ARGUMENT 1 ##
-+####################
-+
-+set_arg1:
-+ srli t1, t0, FFI_FLAG_BITS_X1 # Shift to get the bits for this argument
-+ andi t1, t1, 3 # Mask out the bits for this argument
-+
-+ # when its zero, it means its just a word-sized int/ptr
-+ bne t1, zero, set_arg1_float
-+ lw a1, FFI_SIZEOF_ARG_X1(sp) # load argument
-+ j set_arg2
-+
-+set_arg1_float:
-+ # this is an odd register, so that means we cannot have a double-sized type
-+ # here anyway. we just assume its a float, in this case.
-+ flw fa1, FFI_SIZEOF_ARG_X1(sp) # load argument
-+ j set_arg2
-+
-+####################
-+## SET ARGUMENT 2 ##
-+####################
-+
-+set_arg2:
-+ srli t1, t0, FFI_FLAG_BITS_X2 # Shift to get the bits for this argument
-+ andi t1, t1, 3 # Mask out the bits for this argument
-+
-+ # when its zero, it means its just a word-sized int/ptr
-+ bne t1, zero, set_arg2_float
-+ lw a2, FFI_SIZEOF_ARG_X2(sp) # load argument
-+ j set_arg3
-+
-+set_arg2_float:
-+ addi t1, t1, -1
-+
-+ # when its zero, it means its just a word-sized float
-+ bne t1, zero, set_arg2_longlong
-+ flw fa2, FFI_SIZEOF_ARG_X2(sp) # load argument
-+ j set_arg3
-+
-+set_arg2_longlong:
-+ addi t1, t1, -1
-+
-+ # when its zero, it means its just a double-word-sized int/struct
-+ bne t1, zero, set_arg2_double
-+ lw a2, FFI_SIZEOF_ARG_X2(sp) # load low order bits into even
-+ lw a3, FFI_SIZEOF_ARG_X3(sp) # load high order bits into odd
-+ j set_arg4
-+
-+set_arg2_double:
-+ # otherwise it must be a double we're dealing with
-+ flw fa2, FFI_SIZEOF_ARG_X2(sp) # load low order bits into even
-+ flw fa3, FFI_SIZEOF_ARG_X3(sp) # load high order bits into odd
-+ j set_arg4
-+
-+####################
-+## SET ARGUMENT 3 ##
-+####################
-+
-+set_arg3:
-+ srli t1, t0, FFI_FLAG_BITS_X3 # Shift to get the bits for this argument
-+ andi t1, t1, 3 # Mask out the bits for this argument
-+
-+ # when its zero, it means its just a word-sized int/ptr
-+ bne t1, zero, set_arg3_float
-+ lw a3, FFI_SIZEOF_ARG_X3(sp) # load argument
-+ j set_arg4
-+
-+set_arg3_float:
-+ # this is an odd register, so that means we cannot have a double-sized type
-+ # here anyway. we just assume its a float, in this case.
-+ flw fa3, FFI_SIZEOF_ARG_X3(sp) # load argument
-+ j set_arg4
-+
-+####################
-+## SET ARGUMENT 4 ##
-+####################
-+
-+set_arg4:
-+ srli t1, t0, FFI_FLAG_BITS_X4 # Shift to get the bits for this argument
-+ andi t1, t1, 3 # Mask out the bits for this argument
-+
-+ # when its zero, it means its just a word-sized int/ptr
-+ bne t1, zero, set_arg4_float
-+ lw a4, FFI_SIZEOF_ARG_X4(sp) # load argument
-+ j set_arg5
-+
-+set_arg4_float:
-+ addi t1, t1, -1
-+
-+ # when its zero, it means its just a word-sized float
-+ bne t1, zero, set_arg4_longlong
-+ flw fa4, FFI_SIZEOF_ARG_X4(sp) # load argument
-+ j set_arg5
-+
-+set_arg4_longlong:
-+ addi t1, t1, -1
-+
-+ # when its zero, it means its just a double-word-sized int/struct
-+ bne t1, zero, set_arg4_double
-+ lw a4, FFI_SIZEOF_ARG_X4(sp) # load low order bits into even
-+ lw a5, FFI_SIZEOF_ARG_X5(sp) # load high order bits into odd
-+ j set_arg6
-+
-+set_arg4_double:
-+ # otherwise it must be a double we're dealing with
-+ flw fa4, FFI_SIZEOF_ARG_X4(sp) # load low order bits into even
-+ flw fa5, FFI_SIZEOF_ARG_X5(sp) # load high order bits into odd
-+ j set_arg6
-+
-+####################
-+## SET ARGUMENT 5 ##
-+####################
-+
-+set_arg5:
-+ srli t1, t0, FFI_FLAG_BITS_X5 # Shift to get the bits for this argument
-+ andi t1, t1, 3 # Mask out the bits for this argument
-+
-+ # when its zero, it means its just a word-sized int/ptr
-+ bne t1, zero, set_arg5_float
-+ lw a5, FFI_SIZEOF_ARG_X5(sp) # load argument
-+ j set_arg6
-+
-+set_arg5_float:
-+ # this is an odd register, so that means we cannot have a double-sized type
-+ # here anyway. we just assume its a float, in this case.
-+ flw fa5, FFI_SIZEOF_ARG_X5(sp) # load argument
-+ j set_arg6
-+
-+####################
-+## SET ARGUMENT 6 ##
-+####################
-+
-+set_arg6:
-+ srli t1, t0, FFI_FLAG_BITS_X6 # Shift to get the bits for this argument
-+ andi t1, t1, 3 # Mask out the bits for this argument
-+
-+ # when its zero, it means its just a word-sized int/ptr
-+ bne t1, zero, set_arg6_float
-+ lw a6, FFI_SIZEOF_ARG_X6(sp) # load argument
-+ j set_arg7
-+
-+set_arg6_float:
-+ addi t1, t1, -1
-+
-+ # when its zero, it means its just a word-sized float
-+ bne t1, zero, set_arg6_longlong
-+ flw fa6, FFI_SIZEOF_ARG_X6(sp) # load argument
-+ j set_arg7
-+
-+set_arg6_longlong:
-+ addi t1, t1, -1
-+
-+ # when its zero, it means its just a double-word-sized int/struct
-+ bne t1, zero, set_arg6_double
-+ lw a6, FFI_SIZEOF_ARG_X6(sp) # load low order bits into even
-+ lw a7, FFI_SIZEOF_ARG_X7(sp) # load high order bits into odd
-+ j call_it
-+
-+set_arg6_double:
-+ # otherwise it must be a double we're dealing with
-+ flw fa6, FFI_SIZEOF_ARG_X6(sp) # load low order bits into even
-+ flw fa7, FFI_SIZEOF_ARG_X7(sp) # load high order bits into odd
-+ j call_it
-+
-+####################
-+## SET ARGUMENT 7 ##
-+####################
-+
-+set_arg7:
-+ srli t1, t0, FFI_FLAG_BITS_X7 # Shift to get the bits for this argument
-+ andi t1, t1, 3 # Mask out the bits for this argument
-+
-+ # when its zero, it means its just a word-sized int/ptr
-+ bne t1, zero, set_arg7_float
-+ lw a7, FFI_SIZEOF_ARG_X7(sp) # load argument
-+ j call_it
-+
-+set_arg7_float:
-+ # this is an odd register, so that means we cannot have a double-sized type
-+ # here anyway. we just assume its a float, in this case.
-+ flw fa7, FFI_SIZEOF_ARG_X7(sp) # load argument
-+ j call_it
-+
+#else
+
-+## START RISCV SOFT-FLOAT LOADING ##
-+
-+####################
-+## SET ARGUMENT 0 ##
-+####################
-+
-+set_arg0:
-+ srli t1, t0, FFI_FLAG_BITS_X0 # Shift to get the bits for this argument
-+ andi t1, t1, 3 # Mask out the bits for this argument
-+
-+ # when its zero, it means its just a word-sized int/ptr
-+ bne t1, zero, set_arg0_longlong
-+ lw a0, FFI_SIZEOF_ARG_X0(sp) # load argument
-+ j set_arg1
-+
-+set_arg0_longlong:
-+ # must be a double-word-sized argument
-+ lw a0, FFI_SIZEOF_ARG_X0(sp) # load low order bits into even
-+ lw a1, FFI_SIZEOF_ARG_X1(sp) # load high order bits into odd
-+ j set_arg2
-+
-+####################
-+## SET ARGUMENT 1 ##
-+####################
-+
-+set_arg1:
-+ srli t1, t0, FFI_FLAG_BITS_X1 # Shift to get the bits for this argument
-+ andi t1, t1, 3 # Mask out the bits for this argument
-+
-+ # in this case, the argument must be just word-sized
-+ lw a1, FFI_SIZEOF_ARG_X1(sp) # load argument
-+
-+####################
-+## SET ARGUMENT 2 ##
-+####################
-+
-+set_arg2:
-+ srli t1, t0, FFI_FLAG_BITS_X2 # Shift to get the bits for this argument
-+ andi t1, t1, 3 # Mask out the bits for this argument
-+
-+ # when its zero, it means its just a word-sized int/ptr
-+ bne t1, zero, set_arg2_longlong
-+ lw a2, FFI_SIZEOF_ARG_X2(sp) # load argument
-+ j set_arg3
-+
-+set_arg2_longlong:
-+ # must be a double-word-sized argument
-+ lw a2, FFI_SIZEOF_ARG_X2(sp) # load low order bits into even
-+ lw a3, FFI_SIZEOF_ARG_X3(sp) # load high order bits into odd
-+ j set_arg4
-+
-+####################
-+## SET ARGUMENT 3 ##
-+####################
-+
-+set_arg3:
-+ srli t1, t0, FFI_FLAG_BITS_X3 # Shift to get the bits for this argument
-+ andi t1, t1, 3 # Mask out the bits for this argument
-+
-+ # in this case, the argument must be just word-sized
-+ lw a3, FFI_SIZEOF_ARG_X3(sp) # load argument
-+
-+####################
-+## SET ARGUMENT 4 ##
-+####################
-+
-+set_arg4:
-+ srli t1, t0, FFI_FLAG_BITS_X4 # Shift to get the bits for this argument
-+ andi t1, t1, 3 # Mask out the bits for this argument
-+
-+ # when its zero, it means its just a word-sized int/ptr
-+ bne t1, zero, set_arg4_longlong
-+ lw a4, FFI_SIZEOF_ARG_X4(sp) # load argument
-+ j set_arg5
-+
-+set_arg4_longlong:
-+ # must be a double-word-sized argument
-+ lw a4, FFI_SIZEOF_ARG_X4(sp) # load low order bits into even
-+ lw a5, FFI_SIZEOF_ARG_X5(sp) # load high order bits into odd
-+ j set_arg6
-+
-+####################
-+## SET ARGUMENT 5 ##
-+####################
-+
-+set_arg5:
-+ srli t1, t0, FFI_FLAG_BITS_X5 # Shift to get the bits for this argument
-+ andi t1, t1, 3 # Mask out the bits for this argument
-+
-+ # in this case, the argument must be just word-sized
-+ lw a5, FFI_SIZEOF_ARG_X5(sp) # load argument
-+
-+####################
-+## SET ARGUMENT 6 ##
-+####################
-+
-+set_arg6:
-+ srli t1, t0, FFI_FLAG_BITS_X6 # Shift to get the bits for this argument
-+ andi t1, t1, 3 # Mask out the bits for this argument
-+
-+ # when its zero, it means its just a word-sized int/ptr
-+ bne t1, zero, set_arg6_longlong
-+ lw a6, FFI_SIZEOF_ARG_X6(sp) # load argument
-+ j set_arg7
-+
-+set_arg6_longlong:
-+ addi t1, t1, -1
-+
-+ # must be a double-word-sized argument
-+ lw a6, FFI_SIZEOF_ARG_X6(sp) # load low order bits into even
-+ lw a7, FFI_SIZEOF_ARG_X7(sp) # load high order bits into odd
-+ j call_it
-+
-+####################
-+## SET ARGUMENT 7 ##
-+####################
-+
-+set_arg7:
-+ srli t1, t0, FFI_FLAG_BITS_X7 # Shift to get the bits for this argument
-+ andi t1, t1, 3 # Mask out the bits for this argument
-+
-+ # in this case, the argument must be just word-sized
-+ lw a7, FFI_SIZEOF_ARG_X7(sp) # load argument
-+ j call_it
-+
++#ifdef __riscv64
++ #define REG_S sd
++ #define REG_L ld
++#else
++ #define REG_S sw
++ #define REG_L lw
+#endif
+
-+call_it:
-+ # Load the function pointer
-+ lw t4, FFI_SIZEOF_ARG_X2(fp)
-+
-+ # When the return value pointer is NULL, assume no return value.
-+ lw t1, FFI_SIZEOF_ARG_X1(fp)
-+ beq t1, zero, return_void
-+
-+ # is the return type word-sized? if not, jump ahead
-+ ori t3, zero, FFI_TYPE_INT
-+ bne t2, t3, return_longlong
-+
-+ jalr t4 # call the function
-+
-+ # We reload the return value because it was in a temp reg and
-+ # there was just a function call.
-+ lw t0, FFI_SIZEOF_ARG_X1(fp)
-+ sw a0, 0(t0)
-+ j epilogue
++#endif /* LIBFFI_ASM */
+
-+return_longlong:
-+ # is the return type double-word-sized? if not, jump ahead
-+ ori t3, zero, FFI_TYPE_UINT64
-+#ifndef __riscv_soft_float
-+ bne t2, t3, return_float
-+#else
-+ bne t2, t3s, return_void
-+#endif
++#define FFI_ARGS_D FFI_TYPE_DOUBLE
++#define FFI_ARGS_F FFI_TYPE_FLOAT
++#define FFI_ARGS_DD ((FFI_TYPE_DOUBLE << FFI_FLAG_BITS) + FFI_TYPE_DOUBLE)
++#define FFI_ARGS_FF ((FFI_TYPE_FLOAT << FFI_FLAG_BITS) + FFI_TYPE_FLOAT)
++#define FFI_ARGS_FD ((FFI_TYPE_DOUBLE << FFI_FLAG_BITS) + FFI_TYPE_FLOAT)
++#define FFI_ARGS_DF ((FFI_TYPE_FLOAT << FFI_FLAG_BITS) + FFI_TYPE_DOUBLE)
++#define FFI_TYPE_SMALLSTRUCT FFI_TYPE_UINT8
++#define FFI_TYPE_SMALLSTRUCT2 FFI_TYPE_SINT8
++#define FFI_TYPE_STRUCT_D (FFI_TYPE_STRUCT + (FFI_ARGS_D << 4))
++#define FFI_TYPE_STRUCT_F (FFI_TYPE_STRUCT + (FFI_ARGS_F << 4))
++#define FFI_TYPE_STRUCT_DD (FFI_TYPE_STRUCT + (FFI_ARGS_DD << 4))
++#define FFI_TYPE_STRUCT_FF (FFI_TYPE_STRUCT + (FFI_ARGS_FF << 4))
++#define FFI_TYPE_STRUCT_FD (FFI_TYPE_STRUCT + (FFI_ARGS_FD << 4))
++#define FFI_TYPE_STRUCT_DF (FFI_TYPE_STRUCT + (FFI_ARGS_DF << 4))
++#define FFI_TYPE_STRUCT_SMALL (FFI_TYPE_STRUCT + (5 << 4))
++#define FFI_TYPE_STRUCT_SMALL2 (FFI_TYPE_STRUCT + (6 << 4))
++#define FFI_TYPE_STRUCT_D_SOFT (FFI_TYPE_STRUCT_D + 256)
++#define FFI_TYPE_STRUCT_F_SOFT (FFI_TYPE_STRUCT_F + 256)
++#define FFI_TYPE_STRUCT_DD_SOFT (FFI_TYPE_STRUCT_DD + 256)
++#define FFI_TYPE_STRUCT_FF_SOFT (FFI_TYPE_STRUCT_FF + 256)
++#define FFI_TYPE_STRUCT_FD_SOFT (FFI_TYPE_STRUCT_FD + 256)
++#define FFI_TYPE_STRUCT_DF_SOFT (FFI_TYPE_STRUCT_DF + 256)
++#define FFI_TYPE_STRUCT_SOFT 16
+
-+ jalr t4
-+
-+ # We reload the return value because it was in a temp reg and
-+ # there was just a function call.
-+ lw t0, FFI_SIZEOF_ARG_X1(fp)
-+ sw a1, FFI_SIZEOF_ARG_X1(t0)
-+ sw a0, FFI_SIZEOF_ARG_X0(t0)
-+ j epilogue
++/* ---- Definitions for closures ----------------------------------------- */
+
-+#ifndef __riscv_soft_float
-+return_float:
-+ # is the return type a float? if not, jump ahead
-+ ori t3, zero, FFI_TYPE_FLOAT
-+ bne t2, t3, return_double
-+
-+ jalr t4
-+
-+ # We reload the return value because it was in a temp reg and
-+ # there was just a function call.
-+ lw t0, FFI_SIZEOF_ARG_X1(fp)
-+ fsw fa0, FFI_SIZEOF_ARG_X0(t0)
-+ j epilogue
++#define FFI_CLOSURES 1
++#define FFI_TRAMPOLINE_SIZE 24
++#define FFI_NATIVE_RAW_API 0
++#define FFI_EXTRA_CIF_FIELDS unsigned rstruct_flag
+
-+return_double:
-+ # is the return type a double? if not, give up
-+ ori t3, zero, FFI_TYPE_DOUBLE
-+ bne t2, t3, return_void
-+
-+ jalr t4
-+
-+ # We reload the return value because it was in a temp reg and
-+ # there was just a function call.
-+ lw t0, FFI_SIZEOF_ARG_X1(fp)
-+ fsw fa1, FFI_SIZEOF_ARG_X1(t0)
-+ fsw fa0, FFI_SIZEOF_ARG_X0(t0)
-+ j epilogue
+#endif
-+
-+return_void:
-+ jalr t4
-+
-+epilogue:
-+ add sp, fp, zero
-+ lw fp, FFI_SIZEOF_ARG_X3(sp) # Restore frame pointer
-+ lw ra, FFI_SIZEOF_ARG_X4(sp) # Restore return address
-+ add sp, sp, FFI_SIZEOF_ARG_X8 # Fix stack pointer
-+ jr ra
-+
-+ .size ffi_call_rv32, .-ffi_call_rv32
-diff --git a/src/riscv/rv64.S b/src/riscv/rv64.S
++
+diff --git a/libffi-3.1/src/riscv/sysv.S b/libffi-3.1/src/riscv/sysv.S
new file mode 100644
-index 0000000..b315607
+index 0000000..ed3471f
--- /dev/null
-+++ b/src/riscv/rv64.S
-@@ -0,0 +1,410 @@
++++ b/libffi-3.1/src/riscv/sysv.S
+@@ -0,0 +1,545 @@
+/* -----------------------------------------------------------------------
+ rv64.S - Michael Knyszek 2014
+
@@ -1244,40 +2243,39 @@ index 0000000..b315607
+#define fn a5
+#define fp s0
+
-+# Can't resolve expressions, workaround is
-+# explicit enumeration of values
-+
-+# FFI_SIZEOF_ARG = 8 in this case
-+
-+#define FFI_SIZEOF_ARG_X0 0
-+#define FFI_SIZEOF_ARG_X1 8
-+#define FFI_SIZEOF_ARG_X2 16
-+#define FFI_SIZEOF_ARG_X3 24
-+#define FFI_SIZEOF_ARG_X4 32
-+#define FFI_SIZEOF_ARG_X5 40
-+#define FFI_SIZEOF_ARG_X6 48
-+#define FFI_SIZEOF_ARG_X7 56
-+#define FFI_SIZEOF_ARG_X8 64
++#define FFI_SIZEOF_ARG_X0 (0 * FFI_SIZEOF_ARG)
++#define FFI_SIZEOF_ARG_X1 (1 * FFI_SIZEOF_ARG)
++#define FFI_SIZEOF_ARG_X2 (2 * FFI_SIZEOF_ARG)
++#define FFI_SIZEOF_ARG_X3 (3 * FFI_SIZEOF_ARG)
++#define FFI_SIZEOF_ARG_X4 (4 * FFI_SIZEOF_ARG)
++#define FFI_SIZEOF_ARG_X5 (5 * FFI_SIZEOF_ARG)
++#define FFI_SIZEOF_ARG_X6 (6 * FFI_SIZEOF_ARG)
++#define FFI_SIZEOF_ARG_X7 (7 * FFI_SIZEOF_ARG)
++#define FFI_SIZEOF_ARG_X8 (8 * FFI_SIZEOF_ARG)
+
+#define ARG_MASK 65535
+
-+#define FFI_FLAG_BITS_X0 0
-+#define FFI_FLAG_BITS_X1 2
-+#define FFI_FLAG_BITS_X2 4
-+#define FFI_FLAG_BITS_X3 6
-+#define FFI_FLAG_BITS_X4 8
-+#define FFI_FLAG_BITS_X5 10
-+#define FFI_FLAG_BITS_X6 12
-+#define FFI_FLAG_BITS_X7 14
++#define FFI_FLAG_BITS_X0 (0 * FFI_FLAG_BITS)
++#define FFI_FLAG_BITS_X1 (1 * FFI_FLAG_BITS)
++#define FFI_FLAG_BITS_X2 (2 * FFI_FLAG_BITS)
++#define FFI_FLAG_BITS_X3 (3 * FFI_FLAG_BITS)
++#define FFI_FLAG_BITS_X4 (4 * FFI_FLAG_BITS)
++#define FFI_FLAG_BITS_X5 (5 * FFI_FLAG_BITS)
++#define FFI_FLAG_BITS_X6 (6 * FFI_FLAG_BITS)
++#define FFI_FLAG_BITS_X7 (7 * FFI_FLAG_BITS)
+
+# Stack pointer needs to be 16-byte aligned, so frame size is rounded up
-+# FFI_SIZEOF_ARG should be 4 in the 32-bit case
++#ifdef __riscv64
++# define SIZEOF_FRAME (6 * FFI_SIZEOF_ARG)
++#else
++# define SIZEOF_FRAME (8 * FFI_SIZEOF_ARG)
++#endif
+
+ .text
+ .align 2
-+ .globl ffi_call_rv64
-+ .type ffi_call_rv64, @function
-+ffi_call_rv64:
++ .globl ffi_call_asm
++ .type ffi_call_asm, @function
++ffi_call_asm:
+ ### Prologue
+
+ # a0 - ffi_prep_args pointer
@@ -1287,17 +2285,17 @@ index 0000000..b315607
+ # a4 - rvalue
+ # a5 - function ptr
+
-+ add sp, sp, -FFI_SIZEOF_ARG_X6 # move stack pointer by frame size
-+ # must be 16-byte aligned
++ add sp, sp, -SIZEOF_FRAME # move stack pointer by frame size
++ # must be 16-byte aligned
+
+ # stack ptr points to first argument on stack,
+ # but there should be no arguments on the stack
+
-+ sd flags, FFI_SIZEOF_ARG_X0(sp) # save flags
-+ sd rvalue, FFI_SIZEOF_ARG_X1(sp) # save return value pointer
-+ sd fn, FFI_SIZEOF_ARG_X2(sp) # save function pointer
-+ sd fp, FFI_SIZEOF_ARG_X3(sp) # save frame pointer
-+ sd ra, FFI_SIZEOF_ARG_X4(sp) # save return address
++ REG_S flags, FFI_SIZEOF_ARG_X0(sp) # save flags
++ REG_S rvalue, FFI_SIZEOF_ARG_X1(sp) # save return value pointer
++ REG_S fn, FFI_SIZEOF_ARG_X2(sp) # save function pointer
++ REG_S fp, FFI_SIZEOF_ARG_X3(sp) # save frame pointer
++ REG_S ra, FFI_SIZEOF_ARG_X4(sp) # save return address
+
+ add fp, sp, zero # new frame pointer is updated stack pointer
+ add t4, callback, zero # function ptr to prep_args
@@ -1325,7 +2323,7 @@ index 0000000..b315607
+
+ jalr t4 # call ffi_prep_args
+
-+ ld t0, 0(fp) # load the flags word
++ REG_L t0, 0(fp) # load the flags word
+ srli t2, t0, 16 # shift our return type into t4
+
+ li t1, ARG_MASK
@@ -1345,7 +2343,7 @@ index 0000000..b315607
+
+ # when its zero, it means its just a word-sized int/ptr
+ bne t1, zero, set_arg0_float
-+ ld a0, FFI_SIZEOF_ARG_X0(sp) # load argument
++ REG_L a0, FFI_SIZEOF_ARG_X0(sp) # load argument
+ j set_arg1
+
+set_arg0_float:
@@ -1370,7 +2368,7 @@ index 0000000..b315607
+
+ # when its zero, it means its just a word-sized int/ptr
+ bne t1, zero, set_arg1_float
-+ ld a1, FFI_SIZEOF_ARG_X1(sp) # load argument
++ REG_L a1, FFI_SIZEOF_ARG_X1(sp) # load argument
+ j set_arg2
+
+set_arg1_float:
@@ -1395,7 +2393,7 @@ index 0000000..b315607
+
+ # when its zero, it means its just a word-sized int/ptr
+ bne t1, zero, set_arg2_float
-+ ld a2, FFI_SIZEOF_ARG_X2(sp) # load argument
++ REG_L a2, FFI_SIZEOF_ARG_X2(sp) # load argument
+ j set_arg3
+
+set_arg2_float:
@@ -1420,7 +2418,7 @@ index 0000000..b315607
+
+ # when its zero, it means its just a word-sized int/ptr
+ bne t1, zero, set_arg3_float
-+ ld a3, FFI_SIZEOF_ARG_X3(sp) # load argument
++ REG_L a3, FFI_SIZEOF_ARG_X3(sp) # load argument
+ j set_arg4
+
+set_arg3_float:
@@ -1445,7 +2443,7 @@ index 0000000..b315607
+
+ # when its zero, it means its just a word-sized int/ptr
+ bne t1, zero, set_arg4_float
-+ ld a4, FFI_SIZEOF_ARG_X4(sp) # load argument
++ REG_L a4, FFI_SIZEOF_ARG_X4(sp) # load argument
+ j set_arg5
+
+set_arg4_float:
@@ -1470,7 +2468,7 @@ index 0000000..b315607
+
+ # when its zero, it means its just a word-sized int/ptr
+ bne t1, zero, set_arg5_float
-+ ld a5, FFI_SIZEOF_ARG_X5(sp) # load argument
++ REG_L a5, FFI_SIZEOF_ARG_X5(sp) # load argument
+ j set_arg6
+
+set_arg5_float:
@@ -1495,7 +2493,7 @@ index 0000000..b315607
+
+ # when its zero, it means its just a word-sized int/ptr
+ bne t1, zero, set_arg6_float
-+ ld a6, FFI_SIZEOF_ARG_X6(sp) # load argument
++ REG_L a6, FFI_SIZEOF_ARG_X6(sp) # load argument
+ j set_arg7
+
+set_arg6_float:
@@ -1520,7 +2518,7 @@ index 0000000..b315607
+
+ # when its zero, it means its just a word-sized int/ptr
+ bne t1, zero, set_arg7_float
-+ ld a7, FFI_SIZEOF_ARG_X7(sp) # load argument
++ REG_L a7, FFI_SIZEOF_ARG_X7(sp) # load argument
+ j call_it
+
+set_arg7_float:
@@ -1543,23 +2541,23 @@ index 0000000..b315607
+ # that has a size of >8 bytes. Therefore, we can
+ # just load everything quite easily and nicely.
+
-+ ld a0, FFI_SIZEOF_ARG_X0(sp) # load argument
-+ ld a1, FFI_SIZEOF_ARG_X1(sp) # load argument
-+ ld a2, FFI_SIZEOF_ARG_X2(sp) # load argument
-+ ld a3, FFI_SIZEOF_ARG_X3(sp) # load argument
-+ ld a4, FFI_SIZEOF_ARG_X4(sp) # load argument
-+ ld a5, FFI_SIZEOF_ARG_X5(sp) # load argument
-+ ld a6, FFI_SIZEOF_ARG_X6(sp) # load argument
-+ ld a7, FFI_SIZEOF_ARG_X7(sp) # load argument
++ REG_L a0, FFI_SIZEOF_ARG_X0(sp) # load argument
++ REG_L a1, FFI_SIZEOF_ARG_X1(sp) # load argument
++ REG_L a2, FFI_SIZEOF_ARG_X2(sp) # load argument
++ REG_L a3, FFI_SIZEOF_ARG_X3(sp) # load argument
++ REG_L a4, FFI_SIZEOF_ARG_X4(sp) # load argument
++ REG_L a5, FFI_SIZEOF_ARG_X5(sp) # load argument
++ REG_L a6, FFI_SIZEOF_ARG_X6(sp) # load argument
++ REG_L a7, FFI_SIZEOF_ARG_X7(sp) # load argument
+
+#endif
+
+call_it:
+ # Load the function pointer
-+ ld t4, FFI_SIZEOF_ARG_X2(fp)
++ REG_L t4, FFI_SIZEOF_ARG_X2(fp)
+
+ # When the return value pointer is NULL, assume no return value.
-+ ld t1, FFI_SIZEOF_ARG_X1(fp)
++ REG_L t1, FFI_SIZEOF_ARG_X1(fp)
+ beq t1, zero, return_void
+
+ # is the return type an int? if not, and if we have an FPU,
@@ -1573,8 +2571,8 @@ index 0000000..b315607
+
+ # We reload the return value because it was in a temp reg and
+ # there was just a function call.
-+ ld t0, FFI_SIZEOF_ARG_X1(fp)
-+ sd a0, 0(t0)
++ REG_L t0, FFI_SIZEOF_ARG_X1(fp)
++ REG_S a0, 0(t0)
+ j epilogue
+
+#ifndef __riscv_soft_float
@@ -1587,7 +2585,7 @@ index 0000000..b315607
+
+ # We reload the return value because it was in a temp reg and
+ # there was just a function call.
-+ ld t0, FFI_SIZEOF_ARG_X1(fp)
++ REG_L t0, FFI_SIZEOF_ARG_X1(fp)
+ fsw fa0, FFI_SIZEOF_ARG_X0(t0)
+ j epilogue
+
@@ -1600,7 +2598,7 @@ index 0000000..b315607
+
+ # We reload the return value because it was in a temp reg and
+ # there was just a function call.
-+ ld t0, FFI_SIZEOF_ARG_X1(fp)
++ REG_L t0, FFI_SIZEOF_ARG_X1(fp)
+ fsd fa0, FFI_SIZEOF_ARG_X0(t0)
+ j epilogue
+#endif
@@ -1610,16 +2608,152 @@ index 0000000..b315607
+
+epilogue:
+ add sp, fp, zero
-+ ld fp, FFI_SIZEOF_ARG_X3(sp) # Restore frame pointer
-+ ld ra, FFI_SIZEOF_ARG_X4(sp) # Restore return address
++ REG_L fp, FFI_SIZEOF_ARG_X3(sp) # Restore frame pointer
++ REG_L ra, FFI_SIZEOF_ARG_X4(sp) # Restore return address
+ add sp, sp, FFI_SIZEOF_ARG_X8 # Fix stack pointer
+ jr ra
+
-+ .size ffi_call_rv64, .-ffi_call_rv64
-diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
++ .size ffi_call_asm, .-ffi_call_asm
++
++
++/* ffi_closure_asm. Expects address of the passed-in ffi_closure in t0. */
++
++#define SIZEOF_FRAME2 (20 * FFI_SIZEOF_ARG)
++#define A7_OFF2 (19 * FFI_SIZEOF_ARG)
++#define A6_OFF2 (18 * FFI_SIZEOF_ARG)
++#define A5_OFF2 (17 * FFI_SIZEOF_ARG)
++#define A4_OFF2 (16 * FFI_SIZEOF_ARG)
++#define A3_OFF2 (15 * FFI_SIZEOF_ARG)
++#define A2_OFF2 (14 * FFI_SIZEOF_ARG)
++#define A1_OFF2 (13 * FFI_SIZEOF_ARG)
++#define A0_OFF2 (12 * FFI_SIZEOF_ARG)
++#define FA7_OFF2 (11 * FFI_SIZEOF_ARG)
++#define FA6_OFF2 (10 * FFI_SIZEOF_ARG)
++#define FA5_OFF2 (9 * FFI_SIZEOF_ARG)
++#define FA4_OFF2 (8 * FFI_SIZEOF_ARG)
++#define FA3_OFF2 (7 * FFI_SIZEOF_ARG)
++#define FA2_OFF2 (6 * FFI_SIZEOF_ARG)
++#define FA1_OFF2 (5 * FFI_SIZEOF_ARG)
++#define FA0_OFF2 (4 * FFI_SIZEOF_ARG)
++#define V1_OFF2 (3 * FFI_SIZEOF_ARG)
++#define V0_OFF2 (2 * FFI_SIZEOF_ARG)
++#define RA_OFF2 (1 * FFI_SIZEOF_ARG)
++
++ .align 2
++ .globl ffi_closure_asm
++ .type ffi_closure_asm, @function
++ffi_closure_asm:
++
++ addi sp, sp, -SIZEOF_FRAME2
++ REG_S ra, RA_OFF2(sp) # Save return address
++
++ # Store all possible argument registers. If there are more than
++ # fit in registers, then they were stored on the stack.
++ REG_S a0, A0_OFF2(sp)
++ REG_S a1, A1_OFF2(sp)
++ REG_S a2, A2_OFF2(sp)
++ REG_S a3, A3_OFF2(sp)
++ REG_S a4, A4_OFF2(sp)
++ REG_S a5, A5_OFF2(sp)
++ REG_S a6, A6_OFF2(sp)
++ REG_S a7, A7_OFF2(sp)
++
++ # Store all possible float/double registers.
++ fsd fa0, FA0_OFF2(sp)
++ fsd fa1, FA1_OFF2(sp)
++ fsd fa2, FA2_OFF2(sp)
++ fsd fa3, FA3_OFF2(sp)
++ fsd fa4, FA4_OFF2(sp)
++ fsd fa5, FA5_OFF2(sp)
++ fsd fa6, FA6_OFF2(sp)
++ fsd fa7, FA7_OFF2(sp)
++
++ # Call ffi_closure_riscv_inner to do the real work.
++ move a0, t0 # Pointer to the ffi_closure
++ addi a1, sp, V0_OFF2
++ addi a2, sp, A0_OFF2
++ addi a3, sp, FA0_OFF2
++ call ffi_closure_riscv_inner
++
++ # Return flags are in a0
++ li t0, FFI_TYPE_SINT32
++ bne a0, t0, cls_retint
++ lw a0, V0_OFF2(sp)
++ j cls_epilogue
++
++cls_retint:
++ li t0, FFI_TYPE_INT
++ bne a0, t0, cls_retfloat
++ REG_L a0, V0_OFF2(sp)
++ j cls_epilogue
++
++cls_retfloat:
++ li t0, FFI_TYPE_FLOAT
++ bne a0, t0, cls_retdouble
++ flw fa0, V0_OFF2(sp)
++ j cls_epilogue
++
++cls_retdouble:
++ li t0, FFI_TYPE_DOUBLE
++ bne a0, t0, cls_retstruct_d
++ fld fa0, V0_OFF2(sp)
++ j cls_epilogue
++
++cls_retstruct_d:
++ li t0, FFI_TYPE_STRUCT_D
++ bne a0, t0, cls_retstruct_f
++ fld fa0, V0_OFF2(sp)
++ j cls_epilogue
++
++cls_retstruct_f:
++ li t0, FFI_TYPE_STRUCT_F
++ bne a0, t0, cls_retstruct_d_d
++ flw fa0, V0_OFF2(sp)
++ j cls_epilogue
++
++cls_retstruct_d_d:
++ li t0, FFI_TYPE_STRUCT_DD
++ bne a0, t0, cls_retstruct_f_f
++ fld fa0, V0_OFF2(sp)
++ fld fa1, V1_OFF2(sp)
++ j cls_epilogue
++
++cls_retstruct_f_f:
++ li t0, FFI_TYPE_STRUCT_FF
++ bne a0, t0, cls_retstruct_d_f
++ flw fa0, V0_OFF2(sp)
++ flw fa1, V1_OFF2(sp)
++ j cls_epilogue
++
++cls_retstruct_d_f:
++ li t0, FFI_TYPE_STRUCT_DF
++ bne a0, t0, cls_retstruct_f_d
++ fld fa0, V0_OFF2(sp)
++ flw fa1, V1_OFF2(sp)
++ j cls_epilogue
++
++cls_retstruct_f_d:
++ li t0, FFI_TYPE_STRUCT_FD
++ bne a0, t0, cls_retstruct_small2
++ flw fa0, V0_OFF2(sp)
++ fld fa1, V1_OFF2(sp)
++ j cls_epilogue
++
++cls_retstruct_small2:
++ REG_L a0, V0_OFF2(sp)
++ REG_L a1, V1_OFF2(sp)
++
++# Epilogue
++cls_epilogue:
++ REG_L ra, RA_OFF2(sp) # Restore return address
++ addi sp, sp, SIZEOF_FRAME2
++ ret
++
++ .size ffi_closure_asm, .-ffi_closure_asm
+diff --git a/libffi-3.1/testsuite/Makefile.am b/libffi-3.1/testsuite/Makefile.am
index da10465..d72f122 100644
---- a/testsuite/Makefile.am
-+++ b/testsuite/Makefile.am
+--- a/libffi-3.1/testsuite/Makefile.am
++++ b/libffi-3.1/testsuite/Makefile.am
@@ -34,7 +34,7 @@ libffi.call/cls_12byte.c libffi.call/cls_multi_sshortchar.c \
libffi.call/cls_align_longdouble_split2.c libffi.call/return_dbl2.c \
libffi.call/return_fl3.c libffi.call/stret_medium.c \
@@ -1629,11 +2763,30 @@ index da10465..d72f122 100644
libffi.call/closure_simple.c libffi.call/cls_align_uint16.c \
libffi.call/cls_9byte1.c libffi.call/closure_fn6.c \
libffi.call/cls_double_va.c libffi.call/cls_align_pointer.c \
-diff --git a/testsuite/libffi.call/many3.c b/testsuite/libffi.call/many3.c
+diff --git a/libffi-3.1/testsuite/Makefile.in b/libffi-3.1/testsuite/Makefile.in
+index 99e226c..5bbedb9 100644
+--- a/libffi-3.1/testsuite/Makefile.in
++++ b/libffi-3.1/testsuite/Makefile.in
+@@ -1,4 +1,4 @@
+-# Makefile.in generated by automake 1.13.4 from Makefile.am.
++# Makefile.in generated by automake 1.14.1 from Makefile.am.
+ # @configure_input@
+
+ # Copyright (C) 1994-2013 Free Software Foundation, Inc.
+@@ -297,7 +297,7 @@ libffi.call/cls_12byte.c libffi.call/cls_multi_sshortchar.c \
+ libffi.call/cls_align_longdouble_split2.c libffi.call/return_dbl2.c \
+ libffi.call/return_fl3.c libffi.call/stret_medium.c \
+ libffi.call/nested_struct6.c libffi.call/closure_fn3.c \
+-libffi.call/float3.c libffi.call/many2.c \
++libffi.call/float3.c libffi.call/many2.c libffi.call/many3.c \
+ libffi.call/closure_simple.c libffi.call/cls_align_uint16.c \
+ libffi.call/cls_9byte1.c libffi.call/closure_fn6.c \
+ libffi.call/cls_double_va.c libffi.call/cls_align_pointer.c \
+diff --git a/libffi-3.1/testsuite/libffi.call/many3.c b/libffi-3.1/testsuite/libffi.call/many3.c
new file mode 100644
index 0000000..d7396da
--- /dev/null
-+++ b/testsuite/libffi.call/many3.c
++++ b/libffi-3.1/testsuite/libffi.call/many3.c
@@ -0,0 +1,59 @@
+/* Area: ffi_call
+ Purpose: Check return value int, with many arguments
diff --git a/dev-libs/libffi/libffi-3.1-r3.ebuild b/dev-libs/libffi/libffi-3.1-r3.ebuild
index c68d046..a3a1480 100644
--- a/dev-libs/libffi/libffi-3.1-r3.ebuild
+++ b/dev-libs/libffi/libffi-3.1-r3.ebuild
@@ -40,8 +40,7 @@ src_prepare() {
epatch \
"${FILESDIR}"/${P}-execstack.patch \
"${FILESDIR}"/${P}-typing_error.patch \
- "${FILESDIR}"/${P}-riscv.patch \
- "${FILESDIR}"/${PN}-3.2-riscv-closure.patch
+ "${FILESDIR}"/${P}-riscv.patch
sed -i -e 's:@toolexeclibdir@:$(libdir):g' Makefile.in || die #462814
# http://sourceware.org/ml/libffi-discuss/2014/msg00060.html