[PATCH v2 06/28] Add add_ssaaaa and sub_ssaaaa to gmp-arch.h

Adhemerval Zanella adhemerval.zanella@linaro.org
Tue Oct 28 17:08:15 GMT 2025


To enable “longlong.h” removal, add_ssaaaa and sub_ssaaaa are moved to
gmp-arch.h.  The generic implementation now uses a static inline.  This
provides better type checking than the GNU extension, which casts the
asm constraint. It also works better with clang.

Most architectures use the generic implementation.  This is expanded
from a macro.  Exceptions are arc, arm, hppa, x86, m68k, powerpc, and
sparc.  I kept only the x86 optimization, as there is no easy way to
emit add{q}. For all others, the compiler generates good enough code.

The strongly typed implementation required some changes.  I adjusted
_FP_W_TYPE, _FP_WS_TYPE, and _FP_I_TYPE to use the same type as
mp_limb_t on aarch64, powerpc64le, x86_64, and riscv64.  This basically
means using “long” instead of “long long.”
---
 sysdeps/aarch64/sfp-machine.h                 |  4 +-
 sysdeps/generic/gmp-arch.h                    | 35 ++++++++++++-
 sysdeps/loongarch/sfp-machine.h               |  6 +--
 .../powerpc/powerpc64/le/fpu/sfp-machine.h    |  6 +--
 sysdeps/riscv/sfp-machine.h                   |  6 +--
 sysdeps/x86/fpu/sfp-machine.h                 | 18 ++++---
 sysdeps/x86/gmp-arch.h                        | 52 +++++++++++++++++++
 7 files changed, 109 insertions(+), 18 deletions(-)

diff --git a/sysdeps/aarch64/sfp-machine.h b/sysdeps/aarch64/sfp-machine.h
index b41a9462df..3468e47db3 100644
--- a/sysdeps/aarch64/sfp-machine.h
+++ b/sysdeps/aarch64/sfp-machine.h
@@ -2,9 +2,9 @@
 #include <fpu_control.h>
 
 #define _FP_W_TYPE_SIZE		64
-#define _FP_W_TYPE		unsigned long long
+#define _FP_W_TYPE		unsigned long
 #define _FP_WS_TYPE		signed long long
-#define _FP_I_TYPE		long long
+#define _FP_I_TYPE		long
 
 #define _FP_MUL_MEAT_S(R,X,Y)					\
   _FP_MUL_MEAT_1_imm(_FP_WFRACBITS_S,R,X,Y)
diff --git a/sysdeps/generic/gmp-arch.h b/sysdeps/generic/gmp-arch.h
index 623b0ae968..3ec144562a 100644
--- a/sysdeps/generic/gmp-arch.h
+++ b/sysdeps/generic/gmp-arch.h
@@ -110,4 +110,37 @@ udiv_qrnnd_generic (mp_limb_t *q, mp_limb_t *r, mp_limb_t n1, mp_limb_t n0,
   udiv_qrnnd_generic (&__q, &__r, __n1, __n0, __d)
 
 
-#endif /* __GMP_ARHC_H */
+/* add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1,
+   high_addend_2, low_addend_2) adds two UWtype integers, composed by
+   HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2
+   respectively.  The result is placed in HIGH_SUM and LOW_SUM.  Overflow
+   (i.e. carry out) is not stored anywhere, and is lost.  */
+static __always_inline void
+add_ssaaaa_generic (mp_limb_t *sh, mp_limb_t *sl, mp_limb_t ah,
+		    mp_limb_t al,  mp_limb_t bh,  mp_limb_t bl)
+{
+  *sl = al + bl;
+  *sh = (ah + bh) + (*sl < al);
+}
+#undef add_ssaaaa
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  add_ssaaaa_generic (&sh, &sl, ah, al, bh, bl)
+
+/* sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend,
+   high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers,
+   composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and
+   LOW_SUBTRAHEND_2 respectively.  The result is placed in HIGH_DIFFERENCE
+   and LOW_DIFFERENCE.  Overflow (i.e. carry out) is not stored anywhere,
+   and is lost.  */
+static __always_inline void
+sub_ddmmss_generic (mp_limb_t *sh, mp_limb_t *sl, mp_limb_t ah,
+		    mp_limb_t al,  mp_limb_t bh,  mp_limb_t bl)
+{
+  *sl = al - bl;
+  *sh = (ah - bh) - (*sl > al);
+}
+#undef sub_ddmmss
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  sub_ddmmss_generic (&sh, &sl, ah, al, bh, bl)
+
+#endif
diff --git a/sysdeps/loongarch/sfp-machine.h b/sysdeps/loongarch/sfp-machine.h
index 497b550f5c..113d96651b 100644
--- a/sysdeps/loongarch/sfp-machine.h
+++ b/sysdeps/loongarch/sfp-machine.h
@@ -21,9 +21,9 @@
 #include <fpu_control.h>
 
 #define _FP_W_TYPE_SIZE 64
-#define _FP_W_TYPE unsigned long long
-#define _FP_WS_TYPE signed long long
-#define _FP_I_TYPE long long
+#define _FP_W_TYPE unsigned long
+#define _FP_WS_TYPE signed long
+#define _FP_I_TYPE long
 
 #define _FP_MUL_MEAT_S(R, X, Y) _FP_MUL_MEAT_1_imm (_FP_WFRACBITS_S, R, X, Y)
 #define _FP_MUL_MEAT_D(R, X, Y) \
diff --git a/sysdeps/powerpc/powerpc64/le/fpu/sfp-machine.h b/sysdeps/powerpc/powerpc64/le/fpu/sfp-machine.h
index b4b27f95f4..30b7fcf6ed 100644
--- a/sysdeps/powerpc/powerpc64/le/fpu/sfp-machine.h
+++ b/sysdeps/powerpc/powerpc64/le/fpu/sfp-machine.h
@@ -1,7 +1,7 @@
 #define _FP_W_TYPE_SIZE		64
-#define _FP_W_TYPE		unsigned long long
-#define _FP_WS_TYPE		signed long long
-#define _FP_I_TYPE		long long
+#define _FP_W_TYPE		unsigned long
+#define _FP_WS_TYPE		signed long
+#define _FP_I_TYPE		long
 
 typedef int TItype __attribute__ ((mode (TI)));
 typedef unsigned int UTItype __attribute__ ((mode (TI)));
diff --git a/sysdeps/riscv/sfp-machine.h b/sysdeps/riscv/sfp-machine.h
index 43b2ba10ab..a38edd1e3c 100644
--- a/sysdeps/riscv/sfp-machine.h
+++ b/sysdeps/riscv/sfp-machine.h
@@ -52,9 +52,9 @@
 #else
 
 # define _FP_W_TYPE_SIZE		64
-# define _FP_W_TYPE		unsigned long long
-# define _FP_WS_TYPE		signed long long
-# define _FP_I_TYPE		long long
+# define _FP_W_TYPE		unsigned long
+# define _FP_WS_TYPE		signed long
+# define _FP_I_TYPE		long
 
 # define _FP_MUL_MEAT_S(R, X, Y)					\
   _FP_MUL_MEAT_1_imm (_FP_WFRACBITS_S, R, X, Y)
diff --git a/sysdeps/x86/fpu/sfp-machine.h b/sysdeps/x86/fpu/sfp-machine.h
index 5892f4f5fe..cbcedb8621 100644
--- a/sysdeps/x86/fpu/sfp-machine.h
+++ b/sysdeps/x86/fpu/sfp-machine.h
@@ -8,9 +8,15 @@ typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
 
 #ifdef __x86_64__
 # define _FP_W_TYPE_SIZE	64
-# define _FP_W_TYPE		unsigned long long
-# define _FP_WS_TYPE		signed long long
-# define _FP_I_TYPE		long long
+# ifndef __ILP32__
+#  define _FP_W_TYPE		unsigned long
+#  define _FP_WS_TYPE		signed long
+#  define _FP_I_TYPE		long
+# else
+#  define _FP_W_TYPE		unsigned long long
+#  define _FP_WS_TYPE		signed long long
+#  define _FP_I_TYPE		long long
+# endif
 
 typedef int TItype __attribute__ ((mode (TI)));
 typedef unsigned int UTItype __attribute__ ((mode (TI)));
@@ -45,9 +51,9 @@ typedef unsigned int UTItype __attribute__ ((mode (TI)));
   } while (0)
 #else
 # define _FP_W_TYPE_SIZE	32
-# define _FP_W_TYPE		unsigned int
-# define _FP_WS_TYPE		signed int
-# define _FP_I_TYPE		int
+# define _FP_W_TYPE		unsigned long int
+# define _FP_WS_TYPE		signed long int
+# define _FP_I_TYPE		long int
 
 # define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)	\
   __asm__ ("add{l} {%11,%3|%3,%11}\n\t"				\
diff --git a/sysdeps/x86/gmp-arch.h b/sysdeps/x86/gmp-arch.h
index 5c8b8830af..45f047e1b6 100644
--- a/sysdeps/x86/gmp-arch.h
+++ b/sysdeps/x86/gmp-arch.h
@@ -47,4 +47,56 @@ udiv_qrnnd_x86 (mp_limb_t *q, mp_limb_t *r, mp_limb_t n1, mp_limb_t n0,
 #define udiv_qrnnd(__q, __r, __n1, __n0, __d) \
   udiv_qrnnd_x86 (&__q, &__r, __n1, __n0, __d)
 
+static __always_inline void
+add_ssaaaa_x86 (mp_limb_t *sh, mp_limb_t *sl, mp_limb_t ah,
+		mp_limb_t al, mp_limb_t bh, mp_limb_t bl)
+{
+#ifdef __x86_64__
+  asm ("add{q} {%5,%1|%1,%5}\n\tadc{q} {%3,%0|%0,%3}"
+       : "=r" (*sh),
+         "=&r" (*sl)
+       : "%0" (ah),
+         "rme" (bh),
+	 "%1" (al),
+	 "rme" (bl));
+#else
+  asm ("add{l} {%5,%1|%1,%5}\n\tadc{l} {%3,%0|%0,%3}"
+       : "=r" (*sh),
+         "=&r" (*sl)
+       : "%0" (ah),
+          "g" (bh),
+	  "%1" (al),
+	  "g" (bl));
+#endif
+}
+#undef add_ssaaaa
+#define add_ssaaaa(__sh, __sl, __ah, __al, __bh, __bl) \
+  add_ssaaaa_x86 (&__sh, &__sl, __ah, __al, __bh, __bl)
+
+static __always_inline void
+sub_ddmmss_x86 (mp_limb_t *sh, mp_limb_t *sl, mp_limb_t ah,
+		mp_limb_t al, mp_limb_t bh, mp_limb_t bl)
+{
+#ifdef __x86_64__
+  asm ("sub{q} {%5,%1|%1,%5}\n\tsbb{q} {%3,%0|%0,%3}"
+       : "=r" (*sh),
+         "=&r" (*sl)
+       : "0" (ah),
+         "rme" (bh),
+	 "1" (al),
+	 "rme" (bl));
+#else
+  asm ("sub{l} {%5,%1|%1,%5}\n\tsbb{l} {%3,%0|%0,%3}"
+       : "=r" (*sh),
+         "=&r" (*sl)
+       : "0" (ah),
+         "g" (bh),
+	 "1" (al),
+	 "g" (bl));
+#endif
+}
+#undef sub_ddmmss
+#define sub_ddmmss(__sh, __sl, __ah, __al, __bh, __bl) \
+  sub_ddmmss_x86 (&__sh, &__sl, __ah, __al, __bh, __bl)
+
 #endif
-- 
2.43.0



More information about the Libc-alpha mailing list