1From 399558e5a99db58839e2a9a8802f743d9631466a Mon Sep 17 00:00:00 2001
2From: wuzx <wuzx1226@qq.com>
3Date: Fri, 18 Nov 2022 12:04:50 +0800
4Subject: [PATCH] Add sw64 architecture
5
6Add sw64 architecture in file Makefile.am Makefile.in config.guess config.sub configure configure.host m4/ax_gcc_archflag.m4 src/sw_64/ffi.c src/sw_64/ffitarget.h src/sw_64/internal.h src/sw_64/osf.S src/types.c and testsuite/libffi.go/static-chain.h to support sw64 architecture.
7
8Signed-off-by: wuzx <wuzx1226@qq.com>
9---
10 Makefile.am                        |   2 +
11 Makefile.in                        |  24 ++
12 config.guess                       |   9 +
13 config.sub                         |   1 +
14 configure                          |   2 +-
15 configure.host                     |   6 +
16 m4/ax_gcc_archflag.m4              |   2 +-
17 src/sw_64/ffi.c                    | 521 +++++++++++++++++++++++++++++
18 src/sw_64/ffitarget.h              |  57 ++++
19 src/sw_64/internal.h               |  23 ++
20 src/sw_64/osf.S                    | 282 ++++++++++++++++
21 src/types.c                        |   4 +-
22 testsuite/libffi.go/static-chain.h |   2 +
23 13 files changed, 931 insertions(+), 4 deletions(-)
24 create mode 100644 src/sw_64/ffi.c
25 create mode 100644 src/sw_64/ffitarget.h
26 create mode 100644 src/sw_64/internal.h
27 create mode 100644 src/sw_64/osf.S
28
29diff --git a/Makefile.am b/Makefile.am
30index 1b18198..e29722f 100644
31--- a/Makefile.am
32+++ b/Makefile.am
33@@ -47,6 +47,7 @@ endif
34 
35 noinst_HEADERS = src/aarch64/ffitarget.h src/aarch64/internal.h		\
36 	src/alpha/ffitarget.h src/alpha/internal.h			\
37+	src/sw_64/ffitarget.h src/sw_64/internal.h			\
38 	src/arc/ffitarget.h src/arm/ffitarget.h src/arm/internal.h	\
39 	src/avr32/ffitarget.h src/bfin/ffitarget.h			\
40 	src/cris/ffitarget.h src/csky/ffitarget.h src/frv/ffitarget.h	\
41@@ -67,6 +68,7 @@ noinst_HEADERS = src/aarch64/ffitarget.h src/aarch64/internal.h		\
42 
43 EXTRA_libffi_la_SOURCES = src/aarch64/ffi.c src/aarch64/sysv.S		\
44 	src/aarch64/win64_armasm.S src/alpha/ffi.c src/alpha/osf.S	\
45+	src/sw_64/ffi.c src/sw_64/osf.S
46 	src/arc/ffi.c src/arc/arcompact.S src/arm/ffi.c			\
47 	src/arm/sysv.S src/arm/ffi.c src/arm/sysv_msvc_arm32.S		\
48 	src/avr32/ffi.c src/avr32/sysv.S src/bfin/ffi.c			\
49diff --git a/Makefile.in b/Makefile.in
50index a4b67a7..b4eddc2 100644
51--- a/Makefile.in
52+++ b/Makefile.in
53@@ -202,6 +202,7 @@ am__depfiles_remade = src/$(DEPDIR)/closures.Plo \
54 	src/aarch64/$(DEPDIR)/ffi.Plo src/aarch64/$(DEPDIR)/sysv.Plo \
55 	src/aarch64/$(DEPDIR)/win64_armasm.Plo \
56 	src/alpha/$(DEPDIR)/ffi.Plo src/alpha/$(DEPDIR)/osf.Plo \
57+	src/sw_64/$(DEPDIR)/ffi.Plo src/sw_64/$(DEPDIR)/osf.Plo \
58 	src/arc/$(DEPDIR)/arcompact.Plo src/arc/$(DEPDIR)/ffi.Plo \
59 	src/arm/$(DEPDIR)/ffi.Plo src/arm/$(DEPDIR)/sysv.Plo \
60 	src/arm/$(DEPDIR)/sysv_msvc_arm32.Plo \
61@@ -548,6 +549,7 @@ libffi_la_SOURCES = src/prep_cif.c src/types.c src/raw_api.c \
62 	src/java_raw_api.c src/closures.c src/tramp.c $(am__append_2)
63 noinst_HEADERS = src/aarch64/ffitarget.h src/aarch64/internal.h		\
64 	src/alpha/ffitarget.h src/alpha/internal.h			\
65+	src/sw_64/ffitarget.h src/sw_64/internal.h			\
66 	src/arc/ffitarget.h src/arm/ffitarget.h src/arm/internal.h	\
67 	src/avr32/ffitarget.h src/bfin/ffitarget.h			\
68 	src/cris/ffitarget.h src/csky/ffitarget.h src/frv/ffitarget.h	\
69@@ -568,6 +570,7 @@ noinst_HEADERS = src/aarch64/ffitarget.h src/aarch64/internal.h		\
70 
71 EXTRA_libffi_la_SOURCES = src/aarch64/ffi.c src/aarch64/sysv.S		\
72 	src/aarch64/win64_armasm.S src/alpha/ffi.c src/alpha/osf.S	\
73+	src/sw_64/ffi.c src/sw_64/osf.S	\
74 	src/arc/ffi.c src/arc/arcompact.S src/arm/ffi.c			\
75 	src/arm/sysv.S src/arm/ffi.c src/arm/sysv_msvc_arm32.S		\
76 	src/avr32/ffi.c src/avr32/sysv.S src/bfin/ffi.c			\
77@@ -751,6 +754,16 @@ src/alpha/ffi.lo: src/alpha/$(am__dirstamp) \
78 	src/alpha/$(DEPDIR)/$(am__dirstamp)
79 src/alpha/osf.lo: src/alpha/$(am__dirstamp) \
80 	src/alpha/$(DEPDIR)/$(am__dirstamp)
81+src/sw_64/$(am__dirstamp):
82+	@$(MKDIR_P) src/sw_64
83+	@: > src/sw_64/$(am__dirstamp)
84+src/sw_64/$(DEPDIR)/$(am__dirstamp):
85+	@$(MKDIR_P) src/sw_64/$(DEPDIR)
86+	@: > src/sw_64/$(DEPDIR)/$(am__dirstamp)
87+src/sw_64/ffi.lo: src/sw_64/$(am__dirstamp) \
88+	src/sw_64/$(DEPDIR)/$(am__dirstamp)
89+src/sw_64/osf.lo: src/sw_64/$(am__dirstamp) \
90+	src/sw_64/$(DEPDIR)/$(am__dirstamp)
91 src/arc/$(am__dirstamp):
92 	@$(MKDIR_P) src/arc
93 	@: > src/arc/$(am__dirstamp)
94@@ -1096,6 +1109,8 @@ mostlyclean-compile:
95 	-rm -f src/aarch64/*.lo
96 	-rm -f src/alpha/*.$(OBJEXT)
97 	-rm -f src/alpha/*.lo
98+	-rm -f src/sw_64/*.$(OBJEXT)
99+	-rm -f src/sw_64/*.lo
100 	-rm -f src/arc/*.$(OBJEXT)
101 	-rm -f src/arc/*.lo
102 	-rm -f src/arm/*.$(OBJEXT)
103@@ -1168,6 +1183,8 @@ distclean-compile:
104 @AMDEP_TRUE@@am__include@ @am__quote@src/aarch64/$(DEPDIR)/ffi.Plo@am__quote@ # am--include-marker
105 @AMDEP_TRUE@@am__include@ @am__quote@src/aarch64/$(DEPDIR)/sysv.Plo@am__quote@ # am--include-marker
106 @AMDEP_TRUE@@am__include@ @am__quote@src/aarch64/$(DEPDIR)/win64_armasm.Plo@am__quote@ # am--include-marker
107+@AMDEP_TRUE@@am__include@ @am__quote@src/sw_64/$(DEPDIR)/ffi.Plo@am__quote@ # am--include-marker
108+@AMDEP_TRUE@@am__include@ @am__quote@src/sw_64/$(DEPDIR)/osf.Plo@am__quote@ # am--include-marker
109 @AMDEP_TRUE@@am__include@ @am__quote@src/alpha/$(DEPDIR)/ffi.Plo@am__quote@ # am--include-marker
110 @AMDEP_TRUE@@am__include@ @am__quote@src/alpha/$(DEPDIR)/osf.Plo@am__quote@ # am--include-marker
111 @AMDEP_TRUE@@am__include@ @am__quote@src/arc/$(DEPDIR)/arcompact.Plo@am__quote@ # am--include-marker
112@@ -1311,6 +1328,7 @@ clean-libtool:
113 	-rm -rf .libs _libs
114 	-rm -rf src/.libs src/_libs
115 	-rm -rf src/aarch64/.libs src/aarch64/_libs
116+	-rm -rf src/sw_64/.libs src/sw_64/_libs
117 	-rm -rf src/alpha/.libs src/alpha/_libs
118 	-rm -rf src/arc/.libs src/arc/_libs
119 	-rm -rf src/arm/.libs src/arm/_libs
120@@ -1710,6 +1728,8 @@ distclean-generic:
121 	-rm -f src/$(am__dirstamp)
122 	-rm -f src/aarch64/$(DEPDIR)/$(am__dirstamp)
123 	-rm -f src/aarch64/$(am__dirstamp)
124+	-rm -f src/sw_64/$(DEPDIR)/$(am__dirstamp)
125+	-rm -f src/sw_64/$(am__dirstamp)
126 	-rm -f src/alpha/$(DEPDIR)/$(am__dirstamp)
127 	-rm -f src/alpha/$(am__dirstamp)
128 	-rm -f src/arc/$(DEPDIR)/$(am__dirstamp)
129@@ -1792,6 +1812,8 @@ distclean: distclean-recursive
130 	-rm -f src/aarch64/$(DEPDIR)/ffi.Plo
131 	-rm -f src/aarch64/$(DEPDIR)/sysv.Plo
132 	-rm -f src/aarch64/$(DEPDIR)/win64_armasm.Plo
133+	-rm -f src/sw_64/$(DEPDIR)/ffi.Plo
134+	-rm -f src/sw_64/$(DEPDIR)/osf.Plo
135 	-rm -f src/alpha/$(DEPDIR)/ffi.Plo
136 	-rm -f src/alpha/$(DEPDIR)/osf.Plo
137 	-rm -f src/arc/$(DEPDIR)/arcompact.Plo
138@@ -1930,6 +1952,8 @@ maintainer-clean: maintainer-clean-recursive
139 	-rm -f src/aarch64/$(DEPDIR)/ffi.Plo
140 	-rm -f src/aarch64/$(DEPDIR)/sysv.Plo
141 	-rm -f src/aarch64/$(DEPDIR)/win64_armasm.Plo
142+	-rm -f src/sw_64/$(DEPDIR)/ffi.Plo
143+	-rm -f src/sw_64/$(DEPDIR)/osf.Plo
144 	-rm -f src/alpha/$(DEPDIR)/ffi.Plo
145 	-rm -f src/alpha/$(DEPDIR)/osf.Plo
146 	-rm -f src/arc/$(DEPDIR)/arcompact.Plo
147diff --git a/config.guess b/config.guess
148index e94095c..01a1ef3 100644
149--- a/config.guess
150+++ b/config.guess
151@@ -925,6 +925,15 @@ EOF
152 	UNAME_MACHINE=aarch64_be
153 	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
154 	exit ;;
155+    sw_64:Linux:*:*)
156+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
157+          sw)   UNAME_MACHINE=sw_64 ;;
158+	esac
159+	objdump --private-headers /bin/sh | grep -q ld.so.1
160+	if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
161+	echo ${UNAME_MACHINE}-sunway-linux-${LIBC}
162+	exit ;;
163+
164     alpha:Linux:*:*)
165 	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in
166 	  EV5)   UNAME_MACHINE=alphaev5 ;;
167diff --git a/config.sub b/config.sub
168index 14b5150..bbb4efe 100644
169--- a/config.sub
170+++ b/config.sub
171@@ -1158,6 +1158,7 @@ case $cpu-$vendor in
172 		case $cpu in
173 			1750a | 580 \
174 			| a29k \
175+			| sw_64 \
176 			| aarch64 | aarch64_be \
177 			| abacus \
178 			| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
179diff --git a/configure b/configure
180index 94e149c..f911a05 100755
181--- a/configure
182+++ b/configure
183@@ -17216,7 +17216,7 @@ fi
184          *hypersparc*|*rt62[056]*) ax_gcc_arch="hypersparc v8" ;;
185          *cypress*) ax_gcc_arch=cypress ;;
186      esac ;;
187-
188+  sw_64*) ax_gcc_arch=sw6b ;;
189   alphaev5) ax_gcc_arch=ev5 ;;
190   alphaev56) ax_gcc_arch=ev56 ;;
191   alphapca56) ax_gcc_arch="pca56 ev56" ;;
192diff --git a/configure.host b/configure.host
193index 2682671..372e20b 100644
194--- a/configure.host
195+++ b/configure.host
196@@ -24,6 +24,12 @@ case "${host}" in
197 	HAVE_LONG_DOUBLE='defined(__LONG_DOUBLE_128__)'
198 	SOURCES="ffi.c osf.S"
199 	;;
200+  sw_64*-*-*)
201+	TARGET=SW_64; TARGETDIR=sw_64;
202+	# Support 128-bit long double, changeable via command-line switch.
203+	HAVE_LONG_DOUBLE='defined(__LONG_DOUBLE_128__)'
204+	SOURCES="ffi.c osf.S"
205+	;;
206 
207   arc*-*-*)
208 	TARGET=ARC; TARGETDIR=arc
209diff --git a/m4/ax_gcc_archflag.m4 b/m4/ax_gcc_archflag.m4
210index c52b9b2..de17232 100644
211--- a/m4/ax_gcc_archflag.m4
212+++ b/m4/ax_gcc_archflag.m4
213@@ -174,7 +174,7 @@ case $host_cpu in
214          *hypersparc*|*rt62[[056]]*) ax_gcc_arch="hypersparc v8" ;;
215          *cypress*) ax_gcc_arch=cypress ;;
216      esac ;;
217-
218+  sw_64*) ax_gcc_arch=sw6b ;;
219   alphaev5) ax_gcc_arch=ev5 ;;
220   alphaev56) ax_gcc_arch=ev56 ;;
221   alphapca56) ax_gcc_arch="pca56 ev56" ;;
222diff --git a/src/sw_64/ffi.c b/src/sw_64/ffi.c
223new file mode 100644
224index 0000000..d99668f
225--- /dev/null
226+++ b/src/sw_64/ffi.c
227@@ -0,0 +1,521 @@
228+/* -----------------------------------------------------------------------
229+   ffi.c - Copyright (c) 2012  Anthony Green
230+	   Copyright (c) 1998, 2001, 2007, 2008  Red Hat, Inc.
231+
232+   Alpha Foreign Function Interface
233+
234+   Permission is hereby granted, free of charge, to any person obtaining
235+   a copy of this software and associated documentation files (the
236+   ``Software''), to deal in the Software without restriction, including
237+   without limitation the rights to use, copy, modify, merge, publish,
238+   distribute, sublicense, and/or sell copies of the Software, and to
239+   permit persons to whom the Software is furnished to do so, subject to
240+   the following conditions:
241+
242+   The above copyright notice and this permission notice shall be included
243+   in all copies or substantial portions of the Software.
244+
245+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
246+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
247+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
248+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
249+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
250+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
251+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
252+   DEALINGS IN THE SOFTWARE.
253+   ----------------------------------------------------------------------- */
254+
255+#include <ffi.h>
256+#include <ffi_common.h>
257+#include <stdlib.h>
258+#include "internal.h"
259+
260+/* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
261+   all further uses in this file will refer to the 128-bit type.  */
262+#if defined(__LONG_DOUBLE_128__)
263+# if FFI_TYPE_LONGDOUBLE != 4
264+#  error FFI_TYPE_LONGDOUBLE out of date
265+# endif
266+#else
267+# undef FFI_TYPE_LONGDOUBLE
268+# define FFI_TYPE_LONGDOUBLE 4
269+#endif
270+
271+extern void ffi_call_osf(void *stack, void *frame, unsigned flags,
272+			 void *raddr, void (*fn)(void), void *closure)
273+	FFI_HIDDEN;
274+extern void ffi_closure_osf(void) FFI_HIDDEN;
275+extern void ffi_go_closure_osf(void) FFI_HIDDEN;
276+
277+/* Promote a float value to its in-register double representation.
278+   Unlike actually casting to double, this does not trap on NaN.  */
279+static inline UINT64 lds(void *ptr)
280+{
281+  UINT64 ret;
282+  asm("flds %0,%1" : "=f"(ret) : "m"(*(UINT32 *)ptr));
283+  return ret;
284+}
285+
286+/* And the reverse.  */
287+static inline void sts(void *ptr, UINT64 val)
288+{
289+  asm("fsts %1,%0" : "=m"(*(UINT32 *)ptr) : "f"(val));
290+}
291+
292+ffi_status FFI_HIDDEN
293+ffi_prep_cif_machdep(ffi_cif *cif)
294+{
295+  size_t bytes = 0;
296+  int flags, i, avn;
297+  ffi_type *rtype, *itype;
298+
299+  if (cif->abi != FFI_OSF)
300+    return FFI_BAD_ABI;
301+
302+  /* Compute the size of the argument area.  */
303+  for (i = 0, avn = cif->nargs; i < avn; i++)
304+    {
305+      itype = cif->arg_types[i];
306+      switch (itype->type)
307+	{
308+	case FFI_TYPE_INT:
309+	case FFI_TYPE_SINT8:
310+	case FFI_TYPE_UINT8:
311+	case FFI_TYPE_SINT16:
312+	case FFI_TYPE_UINT16:
313+	case FFI_TYPE_SINT32:
314+	case FFI_TYPE_UINT32:
315+	case FFI_TYPE_SINT64:
316+	case FFI_TYPE_UINT64:
317+	case FFI_TYPE_POINTER:
318+	case FFI_TYPE_FLOAT:
319+	case FFI_TYPE_DOUBLE:
320+	case FFI_TYPE_LONGDOUBLE:
321+	  /* All take one 8 byte slot.  */
322+	  bytes += 8;
323+	  break;
324+
325+	case FFI_TYPE_VOID:
326+	case FFI_TYPE_STRUCT:
327+	  /* Passed by value in N slots.  */
328+	  bytes += FFI_ALIGN(itype->size, FFI_SIZEOF_ARG);
329+	  break;
330+
331+	case FFI_TYPE_COMPLEX:
332+	  /* _Complex long double passed by reference; others in 2 slots.  */
333+	  if (itype->elements[0]->type == FFI_TYPE_LONGDOUBLE)
334+	    bytes += 8;
335+	  else
336+	    bytes += 16;
337+	  break;
338+
339+	default:
340+	  abort();
341+	}
342+    }
343+
344+  /* Set the return type flag */
345+  rtype = cif->rtype;
346+  switch (rtype->type)
347+    {
348+    case FFI_TYPE_VOID:
349+      flags = SW_64_FLAGS(SW_64_ST_VOID, SW_64_LD_VOID);
350+      break;
351+    case FFI_TYPE_INT:
352+    case FFI_TYPE_UINT32:
353+    case FFI_TYPE_SINT32:
354+      flags = SW_64_FLAGS(SW_64_ST_INT, SW_64_LD_INT32);
355+      break;
356+    case FFI_TYPE_FLOAT:
357+      flags = SW_64_FLAGS(SW_64_ST_FLOAT, SW_64_LD_FLOAT);
358+      break;
359+    case FFI_TYPE_DOUBLE:
360+      flags = SW_64_FLAGS(SW_64_ST_DOUBLE, SW_64_LD_DOUBLE);
361+      break;
362+    case FFI_TYPE_UINT8:
363+      flags = SW_64_FLAGS(SW_64_ST_INT, SW_64_LD_UINT8);
364+      break;
365+    case FFI_TYPE_SINT8:
366+      flags = SW_64_FLAGS(SW_64_ST_INT, SW_64_LD_SINT8);
367+      break;
368+    case FFI_TYPE_UINT16:
369+      flags = SW_64_FLAGS(SW_64_ST_INT, SW_64_LD_UINT16);
370+      break;
371+    case FFI_TYPE_SINT16:
372+      flags = SW_64_FLAGS(SW_64_ST_INT, SW_64_LD_SINT16);
373+      break;
374+    case FFI_TYPE_UINT64:
375+    case FFI_TYPE_SINT64:
376+    case FFI_TYPE_POINTER:
377+      flags = SW_64_FLAGS(SW_64_ST_INT, SW_64_LD_INT64);
378+      break;
379+    case FFI_TYPE_LONGDOUBLE:
380+    case FFI_TYPE_STRUCT:
381+      /* Passed in memory, with a hidden pointer.  */
382+      flags = SW_64_RET_IN_MEM;
383+      break;
384+    case FFI_TYPE_COMPLEX:
385+      itype = rtype->elements[0];
386+      switch (itype->type)
387+	{
388+	case FFI_TYPE_FLOAT:
389+	  flags = SW_64_FLAGS(SW_64_ST_CPLXF, SW_64_LD_CPLXF);
390+	  break;
391+	case FFI_TYPE_DOUBLE:
392+	  flags = SW_64_FLAGS(SW_64_ST_CPLXD, SW_64_LD_CPLXD);
393+	  break;
394+	default:
395+	  if (rtype->size <= 8)
396+	    flags = SW_64_FLAGS(SW_64_ST_INT, SW_64_LD_INT64);
397+	  else
398+	    flags = SW_64_RET_IN_MEM;
399+	  break;
400+	}
401+      break;
402+    default:
403+      abort();
404+    }
405+  cif->flags = flags;
406+
407+  /* Include the hidden structure pointer in args requirement.  */
408+  if (flags == SW_64_RET_IN_MEM)
409+    bytes += 8;
410+  /* Minimum size is 6 slots, so that ffi_call_osf can pop them.  */
411+  if (bytes < 6*8)
412+    bytes = 6*8;
413+  cif->bytes = bytes;
414+
415+  return FFI_OK;
416+}
417+
418+static unsigned long
419+extend_basic_type(void *valp, int type, int argn)
420+{
421+  switch (type)
422+    {
423+    case FFI_TYPE_SINT8:
424+      return *(SINT8 *)valp;
425+    case FFI_TYPE_UINT8:
426+      return *(UINT8 *)valp;
427+    case FFI_TYPE_SINT16:
428+      return *(SINT16 *)valp;
429+    case FFI_TYPE_UINT16:
430+      return *(UINT16 *)valp;
431+
432+    case FFI_TYPE_FLOAT:
433+      if (argn < 6)
434+	return lds(valp);
435+      /* FALLTHRU */
436+
437+    case FFI_TYPE_INT:
438+    case FFI_TYPE_SINT32:
439+    case FFI_TYPE_UINT32:
440+      /* Note that unsigned 32-bit quantities are sign extended.  */
441+      return *(SINT32 *)valp;
442+
443+    case FFI_TYPE_SINT64:
444+    case FFI_TYPE_UINT64:
445+    case FFI_TYPE_POINTER:
446+    case FFI_TYPE_DOUBLE:
447+      return *(UINT64 *)valp;
448+
449+    default:
450+      abort();
451+    }
452+}
453+
454+static void
455+ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
456+	      void **avalue, void *closure)
457+{
458+  unsigned long *argp;
459+  long i, avn, argn, flags = cif->flags;
460+  ffi_type **arg_types;
461+  void *frame;
462+
463+  /* If the return value is a struct and we don't have a return
464+     value address then we need to make one.  */
465+  if (rvalue == NULL && flags == SW_64_RET_IN_MEM)
466+    rvalue = alloca(cif->rtype->size);
467+
468+  /* Allocate the space for the arguments, plus 4 words of temp
469+     space for ffi_call_osf.  */
470+  argp = frame = alloca(cif->bytes + 4*FFI_SIZEOF_ARG);
471+  frame += cif->bytes;
472+
473+  argn = 0;
474+  if (flags == SW_64_RET_IN_MEM)
475+    argp[argn++] = (unsigned long)rvalue;
476+
477+  avn = cif->nargs;
478+  arg_types = cif->arg_types;
479+
480+  for (i = 0, avn = cif->nargs; i < avn; i++)
481+    {
482+      ffi_type *ty = arg_types[i];
483+      void *valp = avalue[i];
484+      int type = ty->type;
485+      size_t size;
486+
487+      switch (type)
488+	{
489+	case FFI_TYPE_INT:
490+	case FFI_TYPE_SINT8:
491+	case FFI_TYPE_UINT8:
492+	case FFI_TYPE_SINT16:
493+	case FFI_TYPE_UINT16:
494+	case FFI_TYPE_SINT32:
495+	case FFI_TYPE_UINT32:
496+	case FFI_TYPE_SINT64:
497+	case FFI_TYPE_UINT64:
498+	case FFI_TYPE_POINTER:
499+	case FFI_TYPE_FLOAT:
500+	case FFI_TYPE_DOUBLE:
501+	  argp[argn] = extend_basic_type(valp, type, argn);
502+	  argn++;
503+	  break;
504+
505+	case FFI_TYPE_LONGDOUBLE:
506+	by_reference:
507+	  /* Note that 128-bit long double is passed by reference.  */
508+	  argp[argn++] = (unsigned long)valp;
509+	  break;
510+
511+	case FFI_TYPE_VOID:
512+	case FFI_TYPE_STRUCT:
513+	  size = ty->size;
514+	  memcpy(argp + argn, valp, size);
515+	  argn += FFI_ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
516+	  break;
517+
518+	case FFI_TYPE_COMPLEX:
519+	  type = ty->elements[0]->type;
520+	  if (type == FFI_TYPE_LONGDOUBLE)
521+	    goto by_reference;
522+
523+	  /* Most complex types passed as two separate arguments.  */
524+	  size = ty->elements[0]->size;
525+	  argp[argn] = extend_basic_type(valp, type, argn);
526+	  argp[argn + 1] = extend_basic_type(valp + size, type, argn + 1);
527+	  argn += 2;
528+	  break;
529+
530+	default:
531+	  abort();
532+	}
533+    }
534+
535+  flags = (flags >> SW_64_ST_SHIFT) & 0xff;
536+  ffi_call_osf(argp, frame, flags, rvalue, fn, closure);
537+}
538+
539+void
540+ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
541+{
542+  ffi_call_int(cif, fn, rvalue, avalue, NULL);
543+}
544+
545+void
546+ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
547+	     void **avalue, void *closure)
548+{
549+  ffi_call_int(cif, fn, rvalue, avalue, closure);
550+}
551+
552+ffi_status
553+ffi_prep_closure_loc (ffi_closure* closure,
554+		      ffi_cif* cif,
555+		      void (*fun)(ffi_cif*, void*, void**, void*),
556+		      void *user_data,
557+		      void *codeloc)
558+{
559+  unsigned int *tramp;
560+
561+  if (cif->abi != FFI_OSF)
562+    return FFI_BAD_ABI;
563+
564+  tramp = (unsigned int *) &closure->tramp[0];
565+  tramp[0] = 0x43fb0741;	/* mov $27,$1		*/
566+  tramp[1] = 0x8f7b0010;	/* ldq $27,16($27)	*/
567+  tramp[2] = 0x0ffb0000;	/* jmp $31,($27),0	*/
568+  tramp[3] = 0x43ff075f;	/* nop			*/
569+  *(void **) &tramp[4] = ffi_closure_osf;
570+
571+  closure->cif = cif;
572+  closure->fun = fun;
573+  closure->user_data = user_data;
574+
575+  /* Flush the Icache.
576+
577+     Tru64 UNIX as doesn't understand the imb mnemonic, so use call_pal
578+     instead, since both Compaq as and gas can handle it.
579+
580+     0x86 is PAL_imb in Tru64 UNIX <alpha/pal.h>.  */
581+  asm volatile ("sys_call 0x86" : : : "memory");
582+
583+  return FFI_OK;
584+}
585+
586+ffi_status
587+ffi_prep_go_closure (ffi_go_closure* closure,
588+		     ffi_cif* cif,
589+		     void (*fun)(ffi_cif*, void*, void**, void*))
590+{
591+  if (cif->abi != FFI_OSF)
592+    return FFI_BAD_ABI;
593+
594+  closure->tramp = (void *)ffi_go_closure_osf;
595+  closure->cif = cif;
596+  closure->fun = fun;
597+
598+  return FFI_OK;
599+}
600+
601+long FFI_HIDDEN
602+ffi_closure_osf_inner (ffi_cif *cif,
603+		       void (*fun)(ffi_cif*, void*, void**, void*),
604+		       void *user_data,
605+		       void *rvalue, unsigned long *argp)
606+{
607+  void **avalue;
608+  ffi_type **arg_types;
609+  long i, avn, argn, flags;
610+
611+  avalue = alloca(cif->nargs * sizeof(void *));
612+  flags = cif->flags;
613+  argn = 0;
614+
615+  /* Copy the caller's structure return address to that the closure
616+     returns the data directly to the caller.  */
617+  if (flags == SW_64_RET_IN_MEM)
618+    {
619+      rvalue = (void *) argp[0];
620+      argn = 1;
621+    }
622+
623+  arg_types = cif->arg_types;
624+
625+  /* Grab the addresses of the arguments from the stack frame.  */
626+  for (i = 0, avn = cif->nargs; i < avn; i++)
627+    {
628+      ffi_type *ty = arg_types[i];
629+      int type = ty->type;
630+      void *valp = &argp[argn];
631+      size_t size;
632+
633+      switch (type)
634+	{
635+	case FFI_TYPE_INT:
636+	case FFI_TYPE_SINT8:
637+	case FFI_TYPE_UINT8:
638+	case FFI_TYPE_SINT16:
639+	case FFI_TYPE_UINT16:
640+	case FFI_TYPE_SINT32:
641+	case FFI_TYPE_UINT32:
642+	case FFI_TYPE_SINT64:
643+	case FFI_TYPE_UINT64:
644+	case FFI_TYPE_POINTER:
645+	  argn += 1;
646+	  break;
647+
648+	case FFI_TYPE_VOID:
649+	case FFI_TYPE_STRUCT:
650+	  size = ty->size;
651+	  argn += FFI_ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
652+	  break;
653+
654+	case FFI_TYPE_FLOAT:
655+	  /* Floats coming from registers need conversion from double
656+	     back to float format.  */
657+	  if (argn < 6)
658+	    {
659+	      valp = &argp[argn - 6];
660+	      sts(valp, argp[argn - 6]);
661+	    }
662+	  argn += 1;
663+	  break;
664+
665+	case FFI_TYPE_DOUBLE:
666+	  if (argn < 6)
667+	    valp = &argp[argn - 6];
668+	  argn += 1;
669+	  break;
670+
671+	case FFI_TYPE_LONGDOUBLE:
672+	by_reference:
673+	  /* 128-bit long double is passed by reference.  */
674+	  valp = (void *)argp[argn];
675+	  argn += 1;
676+	  break;
677+
678+	case FFI_TYPE_COMPLEX:
679+	  type = ty->elements[0]->type;
680+	  switch (type)
681+	    {
682+	    case FFI_TYPE_SINT64:
683+	    case FFI_TYPE_UINT64:
684+	      /* Passed as separate arguments, but they wind up sequential.  */
685+	      break;
686+
687+	    case FFI_TYPE_INT:
688+	    case FFI_TYPE_SINT8:
689+	    case FFI_TYPE_UINT8:
690+	    case FFI_TYPE_SINT16:
691+	    case FFI_TYPE_UINT16:
692+	    case FFI_TYPE_SINT32:
693+	    case FFI_TYPE_UINT32:
694+	      /* Passed as separate arguments.  Disjoint, but there's room
695+		 enough in one slot to hold the pair.  */
696+	      size = ty->elements[0]->size;
697+	      memcpy(valp + size, valp + 8, size);
698+	      break;
699+
700+	    case FFI_TYPE_FLOAT:
701+	      /* Passed as separate arguments.  Disjoint, and each piece
702+		 may need conversion back to float.  */
703+	      if (argn < 6)
704+		{
705+		  valp = &argp[argn - 6];
706+		  sts(valp, argp[argn - 6]);
707+		}
708+	      if (argn + 1 < 6)
709+		sts(valp + 4, argp[argn + 1 - 6]);
710+	      else
711+		*(UINT32 *)(valp + 4) = argp[argn + 1];
712+	      break;
713+
714+	    case FFI_TYPE_DOUBLE:
715+	      /* Passed as separate arguments.  Only disjoint if one part
716+		 is in fp regs and the other is on the stack.  */
717+	      if (argn < 5)
718+		valp = &argp[argn - 6];
719+	      else if (argn == 5)
720+		{
721+		  valp = alloca(16);
722+		  ((UINT64 *)valp)[0] = argp[5 - 6];
723+		  ((UINT64 *)valp)[1] = argp[6];
724+		}
725+	      break;
726+
727+	    case FFI_TYPE_LONGDOUBLE:
728+	      goto by_reference;
729+
730+	    default:
731+	      abort();
732+	    }
733+	  argn += 2;
734+	  break;
735+
736+	default:
737+	  abort ();
738+	}
739+
740+      avalue[i] = valp;
741+    }
742+
743+  /* Invoke the closure.  */
744+  fun (cif, rvalue, avalue, user_data);
745+
746+  /* Tell ffi_closure_osf how to perform return type promotions.  */
747+  return (flags >> SW_64_LD_SHIFT) & 0xff;
748+}
749diff --git a/src/sw_64/ffitarget.h b/src/sw_64/ffitarget.h
750new file mode 100644
751index 0000000..a02dbd0
752--- /dev/null
753+++ b/src/sw_64/ffitarget.h
754@@ -0,0 +1,57 @@
755+/* -----------------------------------------------------------------*-C-*-
756+   ffitarget.h - Copyright (c) 2012  Anthony Green
757+                 Copyright (c) 1996-2003  Red Hat, Inc.
758+   Target configuration macros for Alpha.
759+
760+   Permission is hereby granted, free of charge, to any person obtaining
761+   a copy of this software and associated documentation files (the
762+   ``Software''), to deal in the Software without restriction, including
763+   without limitation the rights to use, copy, modify, merge, publish,
764+   distribute, sublicense, and/or sell copies of the Software, and to
765+   permit persons to whom the Software is furnished to do so, subject to
766+   the following conditions:
767+
768+   The above copyright notice and this permission notice shall be included
769+   in all copies or substantial portions of the Software.
770+
771+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
772+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
773+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
774+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
775+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
776+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
777+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
778+   DEALINGS IN THE SOFTWARE.
779+
780+   ----------------------------------------------------------------------- */
781+
782+#ifndef LIBFFI_TARGET_H
783+#define LIBFFI_TARGET_H
784+
785+#ifndef LIBFFI_H
786+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
787+#endif
788+
789+#ifndef LIBFFI_ASM
790+typedef unsigned long          ffi_arg;
791+typedef signed long            ffi_sarg;
792+
793+typedef enum ffi_abi {
794+  FFI_FIRST_ABI = 0,
795+  FFI_OSF,
796+  FFI_LAST_ABI,
797+  FFI_DEFAULT_ABI = FFI_OSF
798+} ffi_abi;
799+#endif
800+
801+#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
802+#define FFI_TARGET_HAS_COMPLEX_TYPE
803+
804+/* ---- Definitions for closures ----------------------------------------- */
805+
806+#define FFI_CLOSURES 1
807+#define FFI_GO_CLOSURES 1
808+#define FFI_TRAMPOLINE_SIZE 24
809+#define FFI_NATIVE_RAW_API 0
810+
811+#endif
812diff --git a/src/sw_64/internal.h b/src/sw_64/internal.h
813new file mode 100644
814index 0000000..1866a8c
815--- /dev/null
816+++ b/src/sw_64/internal.h
817@@ -0,0 +1,23 @@
818+#define SW_64_ST_VOID	0
819+#define SW_64_ST_INT	1
820+#define SW_64_ST_FLOAT	2
821+#define SW_64_ST_DOUBLE	3
822+#define SW_64_ST_CPLXF	4
823+#define SW_64_ST_CPLXD	5
824+
825+#define SW_64_LD_VOID	0
826+#define SW_64_LD_INT64	1
827+#define SW_64_LD_INT32	2
828+#define SW_64_LD_UINT16	3
829+#define SW_64_LD_SINT16	4
830+#define SW_64_LD_UINT8	5
831+#define SW_64_LD_SINT8	6
832+#define SW_64_LD_FLOAT	7
833+#define SW_64_LD_DOUBLE	8
834+#define SW_64_LD_CPLXF	9
835+#define SW_64_LD_CPLXD	10
836+
837+#define SW_64_ST_SHIFT		0
838+#define SW_64_LD_SHIFT		8
839+#define SW_64_RET_IN_MEM	0x10000
840+#define SW_64_FLAGS(S, L)	(((L) << SW_64_LD_SHIFT) | (S))
841diff --git a/src/sw_64/osf.S b/src/sw_64/osf.S
842new file mode 100644
843index 0000000..b4b58e5
844--- /dev/null
845+++ b/src/sw_64/osf.S
846@@ -0,0 +1,282 @@
847+/* -----------------------------------------------------------------------
848+   osf.S - Copyright (c) 1998, 2001, 2007, 2008, 2011, 2014 Red Hat
849+
850+   SW_64/OSF Foreign Function Interface
851+
852+   Permission is hereby granted, free of charge, to any person obtaining
853+   a copy of this software and associated documentation files (the
854+   ``Software''), to deal in the Software without restriction, including
855+   without limitation the rights to use, copy, modify, merge, publish,
856+   distribute, sublicense, and/or sell copies of the Software, and to
857+   permit persons to whom the Software is furnished to do so, subject to
858+   the following conditions:
859+
860+   The above copyright notice and this permission notice shall be included
861+   in all copies or substantial portions of the Software.
862+
863+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
864+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
865+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
866+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
867+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
868+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
869+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
870+   DEALINGS IN THE SOFTWARE.
871+   ----------------------------------------------------------------------- */
872+
873+#define LIBFFI_ASM
874+#include <fficonfig.h>
875+#include <ffi.h>
876+#include <ffi_cfi.h>
877+#include "internal.h"
878+
879+	.arch sw6b
880+	.text
881+
882+/* Aid in building a direct addressed jump table, 4 insns per entry.  */
883+.macro E index
884+	.align	4
885+	.org	99b + \index * 16
886+.endm
887+
888+/* ffi_call_osf (void *stack, void *frame, unsigned flags,
889+		 void *raddr, void (*fnaddr)(void), void *closure)
890+
891+   Bit o trickiness here -- FRAME is the base of the stack frame
892+   for this function.  This has been allocated by ffi_call.  We also
893+   deallocate some of the stack that has been alloca'd.  */
894+
895+	.align	4
896+	.globl	ffi_call_osf
897+	.ent	ffi_call_osf
898+	FFI_HIDDEN(ffi_call_osf)
899+
900+ffi_call_osf:
901+	cfi_startproc
902+	cfi_def_cfa($17, 32)
903+	mov	$16, $30
904+	stl	$26, 0($17)
905+	stl	$15, 8($17)
906+	mov	$17, $15
907+	.prologue 0
908+	cfi_def_cfa_register($15)
909+	cfi_rel_offset($26, 0)
910+	cfi_rel_offset($15, 8)
911+
912+	stl	$18, 16($17)		# save flags into frame
913+	stl	$19, 24($17)		# save rvalue into frame
914+	mov	$20, $27		# fn into place for call
915+	mov	$21, $1			# closure into static chain
916+
917+	# Load up all of the (potential) argument registers.
918+	ldl	$16, 0($30)
919+	fldd	$f16, 0($30)
920+	fldd	$f17, 8($30)
921+	ldl	$17, 8($30)
922+	fldd	$f18, 16($30)
923+	ldl	$18, 16($30)
924+	fldd	$f19, 24($30)
925+	ldl	$19, 24($30)
926+	fldd	$f20, 32($30)
927+	ldl	$20, 32($30)
928+	fldd	$f21, 40($30)
929+	ldl	$21, 40($30)
930+
931+	# Deallocate the register argument area.
932+	ldi	$30, 48($30)
933+
934+	call	$26, ($27), 0
935+0:
936+	ldih	$29, 0($26)		!gpdisp!1
937+	ldl	$2, 24($15)		# reload rvalue
938+	ldi	$29, 0($29)		!gpdisp!1
939+	ldl	$3, 16($15)		# reload flags
940+	ldi	$1, 99f-0b($26)
941+	ldl	$26, 0($15)
942+	ldl	$15, 8($15)
943+	cfi_restore($26)
944+	cfi_restore($15)
945+	cfi_def_cfa($sp, 0)
946+	seleq	$2, SW_64_ST_VOID, $3	# mash null rvalue to void
947+	addl	$3, $3, $3
948+	s8addl	$3, $1, $1		# 99f + stcode * 16
949+	jmp	$31, ($1), $st_int
950+
951+	.align	4
952+99:
953+E SW_64_ST_VOID
954+	ret
955+E SW_64_ST_INT
956+$st_int:
957+	stl	$0, 0($2)
958+	ret
959+E SW_64_ST_FLOAT
960+	fsts	$f0, 0($2)
961+	ret
962+E SW_64_ST_DOUBLE
963+	fstd	$f0, 0($2)
964+	ret
965+E SW_64_ST_CPLXF
966+	fsts	$f0, 0($2)
967+	fsts	$f1, 4($2)
968+	ret
969+E SW_64_ST_CPLXD
970+	fstd	$f0, 0($2)
971+	fstd	$f1, 8($2)
972+	ret
973+
974+	cfi_endproc
975+	.end	ffi_call_osf
976+
977+/* ffi_closure_osf(...)
978+
979+   Receives the closure argument in $1.   */
980+
981+#define CLOSURE_FS	(16*8)
982+
983+	.align	4
984+	.globl	ffi_go_closure_osf
985+	.ent	ffi_go_closure_osf
986+	FFI_HIDDEN(ffi_go_closure_osf)
987+
988+ffi_go_closure_osf:
989+	cfi_startproc
990+	ldgp	$29, 0($27)
991+	subl	$30, CLOSURE_FS, $30
992+	cfi_adjust_cfa_offset(CLOSURE_FS)
993+	stl	$26, 0($30)
994+	.prologue 1
995+	cfi_rel_offset($26, 0)
996+
997+	stl	$16, 10*8($30)
998+	stl	$17, 11*8($30)
999+	stl	$18, 12*8($30)
1000+
1001+	ldl	$16, 8($1)			# load cif
1002+	ldl	$17, 16($1)			# load fun
1003+	mov	$1, $18				# closure is user_data
1004+	br	$do_closure
1005+
1006+	cfi_endproc
1007+	.end	ffi_go_closure_osf
1008+
1009+	.align	4
1010+	.globl	ffi_closure_osf
1011+	.ent	ffi_closure_osf
1012+	FFI_HIDDEN(ffi_closure_osf)
1013+
1014+ffi_closure_osf:
1015+	cfi_startproc
1016+	ldgp	$29, 0($27)
1017+	subl	$30, CLOSURE_FS, $30
1018+	cfi_adjust_cfa_offset(CLOSURE_FS)
1019+	stl	$26, 0($30)
1020+	.prologue 1
1021+	cfi_rel_offset($26, 0)
1022+
1023+	# Store all of the potential argument registers in va_list format.
1024+	stl	$16, 10*8($30)
1025+	stl	$17, 11*8($30)
1026+	stl	$18, 12*8($30)
1027+
1028+	ldl	$16, 24($1)			# load cif
1029+	ldl	$17, 32($1)			# load fun
1030+	ldl	$18, 40($1)			# load user_data
1031+
1032+$do_closure:
1033+	stl	$19, 13*8($30)
1034+	stl	$20, 14*8($30)
1035+	stl	$21, 15*8($30)
1036+	fstd	$f16, 4*8($30)
1037+	fstd	$f17, 5*8($30)
1038+	fstd	$f18, 6*8($30)
1039+	fstd	$f19, 7*8($30)
1040+	fstd	$f20, 8*8($30)
1041+        fstd	$f21, 9*8($30)
1042+
1043+	# Call ffi_closure_osf_inner to do the bulk of the work.
1044+	ldi	$19, 2*8($30)
1045+	ldi	$20, 10*8($30)
1046+	call	$26, ffi_closure_osf_inner
1047+0:
1048+	ldih	$29, 0($26)			!gpdisp!2
1049+	ldi	$2, 99f-0b($26)
1050+	s4addl	$0, 0, $1			# ldcode * 4
1051+	ldl	$0, 16($30)			# preload return value
1052+	s4addl	$1, $2, $1			# 99f + ldcode * 16
1053+	ldi	$29, 0($29)			!gpdisp!2
1054+	ldl	$26, 0($30)
1055+	cfi_restore($26)
1056+	jmp	$31, ($1), $load_32
1057+
1058+.macro epilogue
1059+	addl	$30, CLOSURE_FS, $30
1060+	cfi_adjust_cfa_offset(-CLOSURE_FS)
1061+	ret
1062+	.align	4
1063+	cfi_adjust_cfa_offset(CLOSURE_FS)
1064+.endm
1065+
1066+	.align 4
1067+99:
1068+E SW_64_LD_VOID
1069+	epilogue
1070+
1071+E SW_64_LD_INT64
1072+	epilogue
1073+
1074+E SW_64_LD_INT32
1075+$load_32:
1076+	sextl	$0, $0
1077+	epilogue
1078+
1079+E SW_64_LD_UINT16
1080+	zapnot	$0, 3, $0
1081+	epilogue
1082+
1083+E SW_64_LD_SINT16
1084+#ifdef __sw_64_bwx__
1085+	sexth	$0, $0
1086+#else
1087+	sll	$0, 48, $0
1088+	sra	$0, 48, $0
1089+#endif
1090+	epilogue
1091+
1092+E SW_64_LD_UINT8
1093+	and	$0, 0xff, $0
1094+	epilogue
1095+
1096+E SW_64_LD_SINT8
1097+#ifdef __sw_64_bwx__
1098+	sextb	$0, $0
1099+#else
1100+	sll	$0, 56, $0
1101+	sra	$0, 56, $0
1102+#endif
1103+	epilogue
1104+
1105+E SW_64_LD_FLOAT
1106+	flds	$f0, 16($sp)
1107+	epilogue
1108+
1109+E SW_64_LD_DOUBLE
1110+	fldd	$f0, 16($sp)
1111+	epilogue
1112+
1113+E SW_64_LD_CPLXF
1114+	flds	$f0, 16($sp)
1115+	flds	$f1, 20($sp)
1116+	epilogue
1117+
1118+E SW_64_LD_CPLXD
1119+        fldd	$f0, 16($sp)
1120+	fldd	$f1, 24($sp)
1121+	epilogue
1122+
1123+	cfi_endproc
1124+	.end	ffi_closure_osf
1125+
1126+#if defined __ELF__ && defined __linux__
1127+	.section	.note.GNU-stack,"",@progbits
1128+#endif
1129diff --git a/src/types.c b/src/types.c
1130index 9ec27f6..e5f666b 100644
1131--- a/src/types.c
1132+++ b/src/types.c
1133@@ -80,13 +80,13 @@ FFI_TYPEDEF(pointer, void*, FFI_TYPE_POINTER, const);
1134 FFI_TYPEDEF(float, float, FFI_TYPE_FLOAT, const);
1135 FFI_TYPEDEF(double, double, FFI_TYPE_DOUBLE, const);
1136 
1137-#if !defined HAVE_LONG_DOUBLE_VARIANT || defined __alpha__
1138+#if !defined HAVE_LONG_DOUBLE_VARIANT || defined __alpha__ || defined __sw_64__
1139 #define FFI_LDBL_CONST const
1140 #else
1141 #define FFI_LDBL_CONST
1142 #endif
1143 
1144-#ifdef __alpha__
1145+#if defined __alpha__ || defined __sw_64__
1146 /* Even if we're not configured to default to 128-bit long double, 
1147    maintain binary compatibility, as -mlong-double-128 can be used
1148    at any time.  */
1149diff --git a/testsuite/libffi.go/static-chain.h b/testsuite/libffi.go/static-chain.h
1150index 3675b40..25ef76e 100644
1151--- a/testsuite/libffi.go/static-chain.h
1152+++ b/testsuite/libffi.go/static-chain.h
1153@@ -2,6 +2,8 @@
1154 # define STATIC_CHAIN_REG  "x18"
1155 #elif defined(__alpha__)
1156 # define STATIC_CHAIN_REG  "$1"
1157+#elif defined(__sw_64__)
1158+# define STATIC_CHAIN_REG  "$1"
1159 #elif defined(__arm__)
1160 # define STATIC_CHAIN_REG  "ip"
1161 #elif defined(__sparc__)
1162-- 
11632.33.0
1164
1165