diff --git a/build-aux/config.guess b/build-aux/config.guess
index e81d3ae..fc4976f 100755
--- a/build-aux/config.guess
+++ b/build-aux/config.guess
@@ -973,6 +973,16 @@ EOF
 	UNAME_MACHINE=aarch64_be
 	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
 	;;
+#if defined (__sw_64)
+    sw_64:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in
+	  sw)   UNAME_MACHINE=sw_64 ;;
+	esac
+	objdump --private-headers /bin/sh | grep -q ld.so.1
+	if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
+	GUESS=$UNAME_MACHINE-sunway-linux-$LIBC
+	;;
+#endif
     alpha:Linux:*:*)
 	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in
 	  EV5)   UNAME_MACHINE=alphaev5 ;;
diff --git a/build-aux/config.sub b/build-aux/config.sub
index d74fb6d..b5b01c1 100755
--- a/build-aux/config.sub
+++ b/build-aux/config.sub
@@ -1177,6 +1177,9 @@ case $cpu-$vendor in
 			| a29k \
 			| aarch64 | aarch64_be \
 			| abacus \
+#if defined (__sw_64)
+			| sw_64 \
+#endif
 			| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
 			| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \
 			| alphapca5[67] | alpha64pca5[67] \
diff --git a/configure b/configure
index ee54aad..dd92158 100755
--- a/configure
+++ b/configure
@@ -7845,6 +7845,12 @@ printf "%s\n" "#define _LARGEFILE_SOURCE 1" >>confdefs.h
   # (according to the test results of Bruno Haible's ieeefp/fenv_default.m4
   # and the GCC 4.1.2 manual).
   case "$host_cpu" in
+    sw_64*)
+      if test -n "$GCC"; then
+        # GCC has the option -mieee.
+        CPPFLAGS="$CPPFLAGS -mieee"
+      fi
+      ;;
     alpha*)
       # On Alpha systems, a compiler option provides the behaviour.
       # See the ieee(3) manual page, also available at
@@ -18808,7 +18814,7 @@ else $as_nop
        case "$gl_cv_host_cpu_c_abi" in
          i386 | x86_64-x32 | arm | armhf | arm64-ilp32 | hppa | ia64-ilp32 | mips | mipsn32 | powerpc | riscv*-ilp32* | s390 | sparc)
            gl_cv_host_cpu_c_abi_32bit=yes ;;
-         x86_64 | alpha | arm64 | hppa64 | ia64 | mips64 | powerpc64 | powerpc64-elfv2 | riscv*-lp64* | s390x | sparc64 )
+         x86_64 | alpha | arm64 | hppa64 | ia64 | mips64 | powerpc64 | sw_64 | powerpc64-elfv2 | riscv*-lp64* | s390x | sparc64 )
            gl_cv_host_cpu_c_abi_32bit=no ;;
          *)
            gl_cv_host_cpu_c_abi_32bit=unknown ;;
@@ -18838,7 +18844,7 @@ else $as_nop
 
          # CPUs that only support a 64-bit ABI.
          alpha | alphaev[4-8] | alphaev56 | alphapca5[67] | alphaev6[78] \
-         | mmix )
+         | sw_64* | mmix )
            gl_cv_host_cpu_c_abi_32bit=no
            ;;
 
diff --git a/lib/uname.c b/lib/uname.c
index adb9d98..0d6284b 100644
--- a/lib/uname.c
+++ b/lib/uname.c
@@ -228,6 +228,12 @@ uname (struct utsname *buf)
           case PROCESSOR_ARCHITECTURE_MIPS:
             strcpy (buf->machine, "mips");
             break;
+#if defined (__sw_64)
+          case PROCESSOR_ARCHITECTURE_SW_64:
+          case PROCESSOR_ARCHITECTURE_SW_6464:
+            strcpy (buf->machine, "sw_64");
+            break;
+#endif
           case PROCESSOR_ARCHITECTURE_ALPHA:
           case PROCESSOR_ARCHITECTURE_ALPHA64:
             strcpy (buf->machine, "alpha");
diff --git a/m4/fpieee.m4 b/m4/fpieee.m4
index 3f16957..7a6010b 100644
--- a/m4/fpieee.m4
+++ b/m4/fpieee.m4
@@ -30,6 +30,12 @@ AC_DEFUN([gl_FP_IEEE],
   # (according to the test results of Bruno Haible's ieeefp/fenv_default.m4
   # and the GCC 4.1.2 manual).
   case "$host_cpu" in
+    sw_64*)
+      if test -n "$GCC"; then
+        # GCC has the option -mieee.
+        CPPFLAGS="$CPPFLAGS -mieee"
+      fi
+      ;;
     alpha*)
       # On Alpha systems, a compiler option provides the behaviour.
       # See the ieee(3) manual page, also available at
diff --git a/m4/host-cpu-c-abi.m4 b/m4/host-cpu-c-abi.m4
index 64e28b1..e2833aa 100644
--- a/m4/host-cpu-c-abi.m4
+++ b/m4/host-cpu-c-abi.m4
@@ -90,6 +90,12 @@ changequote([,])dnl
            [gl_cv_host_cpu_c_abi=i386])
          ;;
 
+changequote(,)dnl
+       sw_64* )
+changequote([,])dnl
+         gl_cv_host_cpu_c_abi=sw_64
+         ;;
+
 changequote(,)dnl
        alphaev[4-8] | alphaev56 | alphapca5[67] | alphaev6[78] )
 changequote([,])dnl
@@ -355,6 +361,9 @@ EOF
 #ifndef __x86_64__
 #undef __x86_64__
 #endif
+#ifndef __sw_64__
+#undef __sw_64__
+#endif
 #ifndef __alpha__
 #undef __alpha__
 #endif
@@ -468,7 +477,7 @@ AC_DEFUN([gl_HOST_CPU_C_ABI_32BIT],
        case "$gl_cv_host_cpu_c_abi" in
          i386 | x86_64-x32 | arm | armhf | arm64-ilp32 | hppa | ia64-ilp32 | mips | mipsn32 | powerpc | riscv*-ilp32* | s390 | sparc)
            gl_cv_host_cpu_c_abi_32bit=yes ;;
-         x86_64 | alpha | arm64 | hppa64 | ia64 | mips64 | powerpc64 | powerpc64-elfv2 | riscv*-lp64* | s390x | sparc64 )
+         x86_64 | alpha | arm64 | hppa64 | ia64 | mips64 | powerpc64 | powerpc64-elfv2 | sw_64 | riscv*-lp64* | s390x | sparc64 )
            gl_cv_host_cpu_c_abi_32bit=no ;;
          *)
            gl_cv_host_cpu_c_abi_32bit=unknown ;;
@@ -499,7 +508,7 @@ AC_DEFUN([gl_HOST_CPU_C_ABI_32BIT],
          # CPUs that only support a 64-bit ABI.
 changequote(,)dnl
          alpha | alphaev[4-8] | alphaev56 | alphapca5[67] | alphaev6[78] \
-         | mmix )
+         | sw_64* | mmix )
 changequote([,])dnl
            gl_cv_host_cpu_c_abi_32bit=no
            ;;
diff --git a/src/longlong.h b/src/longlong.h
index fbd3716..c99a554 100644
--- a/src/longlong.h
+++ b/src/longlong.h
@@ -170,6 +170,92 @@ along with this file.  If not, see https://www.gnu.org/licenses/.  */
    don't need to be under !NO_ASM */
 #if ! defined (NO_ASM)
 
+#if defined (__sw_64) && W_TYPE_SIZE == 64
+/* Most sw_64-based machines, except Cray systems. */
+#if defined (__GNUC__)
+#if __GMP_GNUC_PREREQ (3,3)
+#define umul_ppmm(ph, pl, m0, m1) \
+  do {                                                                 \
+    UDItype __m0 = (m0), __m1 = (m1);                                  \
+    (ph) = __builtin_sw_64_umulh (__m0, __m1);                         \
+    (pl) = __m0 * __m1;                                                        \
+  } while (0)
+#else
+#define umul_ppmm(ph, pl, m0, m1) \
+  do {                                                                 \
+    UDItype __m0 = (m0), __m1 = (m1);                                  \
+    __asm__ ("umulh %r1,%2,%0"                                         \
+            : "=r" (ph)                                                \
+            : "%rJ" (__m0), "rI" (__m1));                              \
+    (pl) = __m0 * __m1;                                                        \
+  } while (0)
+#endif
+#else /* ! __GNUC__ */
+#include <machine/builtins.h>
+#define umul_ppmm(ph, pl, m0, m1) \
+  do {                                                                 \
+    UDItype __m0 = (m0), __m1 = (m1);                                  \
+    (ph) = __UMULH (__m0, __m1);                                       \
+    (pl) = __m0 * __m1;                                                        \
+  } while (0)
+#endif
+#ifndef LONGLONG_STANDALONE
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  do { UWtype __di;                                                    \
+    __di = __MPN(invert_limb) (d);                                     \
+    udiv_qrnnd_preinv (q, r, n1, n0, d, __di);                         \
+  } while (0)
+#define UDIV_PREINV_ALWAYS  1
+#define UDIV_NEEDS_NORMALIZATION 1
+#endif /* LONGLONG_STANDALONE */
+
+/* clz_tab is required in all configurations, since mpn/sw_64/cntlz.asm
+   always goes into libgmp.so, even when not actually used.  */
+#define COUNT_LEADING_ZEROS_NEED_CLZ_TAB
+
+#if defined (__GNUC__) && HAVE_HOST_CPU_sw_64_CIX
+#define count_leading_zeros(COUNT,X) \
+  __asm__("ctlz %1,%0" : "=r"(COUNT) : "r"(X))
+#define count_trailing_zeros(COUNT,X) \
+  __asm__("cttz %1,%0" : "=r"(COUNT) : "r"(X))
+#endif /* clz/ctz using cix */
+
+#if ! defined (count_leading_zeros)                            \
+  && defined (__GNUC__) && ! defined (LONGLONG_STANDALONE)
+/* SW_64_CMPBGE_0 gives "cmpbge $31,src,dst", ie. test src bytes == 0.
+   "$31" is written explicitly in the asm, since an "r" constraint won't
+   select reg 31.  There seems no need to worry about "r31" syntax for cray,
+   since gcc itself (pre-release 3.4) emits just $31 in various places.         */
+#define SW_64_CMPBGE_0(dst, src)                                       \
+  do { asm ("cmpbge $31, %1, %0" : "=r" (dst) : "r" (src)); } while (0)
+/* Zero bytes are turned into bits with cmpbge, a __clz_tab lookup counts
+   them, locating the highest non-zero byte.  A second __clz_tab lookup
+   counts the leading zero bits in that byte, giving the result.  */
+#define count_leading_zeros(count, x)                                  \
+  do {                                                                 \
+    UWtype  __clz__b, __clz__c, __clz__x = (x);                                \
+    SW_64_CMPBGE_0 (__clz__b,  __clz__x);          /* zero bytes */    \
+    __clz__b = __clz_tab [(__clz__b >> 1) ^ 0x7F];  /* 8 to 1 byte */  \
+    __clz__b = __clz__b * 8 - 7;                   /* 57 to 1 shift */ \
+    __clz__x >>= __clz__b;                                             \
+    __clz__c = __clz_tab [__clz__x];               /* 8 to 1 bit */    \
+    __clz__b = 65 - __clz__b;                                          \
+    (count) = __clz__b - __clz__c;                                     \
+  } while (0)
+#define COUNT_LEADING_ZEROS_NEED_CLZ_TAB
+#endif /* clz using cmpbge */
+
+#if ! defined (count_leading_zeros) && ! defined (LONGLONG_STANDALONE)
+#if HAVE_ATTRIBUTE_CONST
+long __MPN(count_leading_zeros) (UDItype) __attribute__ ((const));
+#else
+long __MPN(count_leading_zeros) (UDItype);
+#endif
+#define count_leading_zeros(count, x) \
+  ((count) = __MPN(count_leading_zeros) (x))
+#endif /* clz using mpn */
+#endif /* __sw_64 */
+
 #if defined (__alpha) && W_TYPE_SIZE == 64
 /* Most alpha-based machines, except Cray systems. */
 #if defined (__GNUC__)
-- 
2.43.0

