[PATCH 1/3] mpi/longlong: provide generic implementation using double word type
Jussi Kivilinna
jussi.kivilinna at iki.fi
Tue Oct 4 20:48:15 CEST 2022
* configure.ac: Add check for 'unsigned __int128'.
* mpi/longlong.h (UDWtype): Define for 32-bit or 64-bit when
'unsigned long long' or 'unsigned __int128' is available.
(add_ssaaaa, sub_ddmmss, umul_ppmm, udiv_qrnnd) [UDWtype]: New.
--
New generic longlong.h implementation by using 'unsigned long long'
on 32-bit and 'unsigned __int128' on 64-bit (for new architectures like
RISC-V).
Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
configure.ac | 1 +
mpi/longlong.h | 75 ++++++++++++++++++++++++++++++++++++++++++++------
2 files changed, 68 insertions(+), 8 deletions(-)
diff --git a/configure.ac b/configure.ac
index c39257b5..6f68a945 100644
--- a/configure.ac
+++ b/configure.ac
@@ -360,6 +360,7 @@ AC_CHECK_SIZEOF(unsigned short, 2)
AC_CHECK_SIZEOF(unsigned int, 4)
AC_CHECK_SIZEOF(unsigned long, 4)
AC_CHECK_SIZEOF(unsigned long long, 0)
+AC_CHECK_SIZEOF(unsigned __int128, 0)
AC_CHECK_SIZEOF(void *, 0)
AC_TYPE_UINTPTR_T
diff --git a/mpi/longlong.h b/mpi/longlong.h
index c299534c..6a829f49 100644
--- a/mpi/longlong.h
+++ b/mpi/longlong.h
@@ -20,18 +20,28 @@ along with this file; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
+/* On 32-bit, use 64-bit 'unsigned long long' for UDWtype, if available. */
+#if !defined (UDWtype) && SIZEOF_UNSIGNED_LONG_LONG * 8 == W_TYPE_SIZE * 2
+# define UDWtype unsigned long long
+#endif
+
+/* On 64-bit, use 128-bit 'unsigned __int128' for UDWtype, if available. */
+#if !defined (UDWtype) && SIZEOF_UNSIGNED___INT128 * 8 == W_TYPE_SIZE * 2
+# define UDWtype unsigned __int128
+#endif
+
/* You have to define the following before including this file:
- UWtype -- An unsigned type, default type for operations (typically a "word")
+ UWtype -- An unsigned type, default type for operations (typically a "word").
UHWtype -- An unsigned type, at least half the size of UWtype.
- UDWtype -- An unsigned type, at least twice as large a UWtype
- W_TYPE_SIZE -- size in bits of UWtype
+ UDWtype -- An unsigned type, at least twice as large a UWtype.
+ W_TYPE_SIZE -- size in bits of UWtype.
SItype, USItype -- Signed and unsigned 32 bit types.
DItype, UDItype -- Signed and unsigned 64 bit types.
- On a 32 bit machine UWtype should typically be USItype;
- on a 64 bit machine, UWtype should typically be UDItype.
+ On a 32 bit machine UWtype should typically be USItype.
+ On a 64 bit machine, UWtype should typically be UDItype.
*/
#define __BITS4 (W_TYPE_SIZE / 4)
@@ -1617,7 +1627,21 @@ typedef unsigned int UTItype __attribute__ ((mode (TI)));
/* If this machine has no inline assembler, use C macros. */
-#if !defined (add_ssaaaa)
+#if !defined (add_ssaaaa) && defined (UDWtype)
+/* Use double word type when available. */
+# define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ do { \
+ UDWtype __audw = (ah); \
+ UDWtype __budw = (bh); \
+ __audw <<= W_TYPE_SIZE; \
+ __audw |= (al); \
+ __budw <<= W_TYPE_SIZE; \
+ __budw |= (bl); \
+ __audw += __budw; \
+ (sh) = (UWtype)(__audw >> W_TYPE_SIZE); \
+ (sl) = (UWtype)(__audw); \
+ } while (0)
+#elif !defined (add_ssaaaa)
# define add_ssaaaa(sh, sl, ah, al, bh, bl) \
do { \
UWtype __x; \
@@ -1627,7 +1651,21 @@ typedef unsigned int UTItype __attribute__ ((mode (TI)));
} while (0)
#endif
-#if !defined (sub_ddmmss)
+#if !defined (sub_ddmmss) && defined (UDWtype)
+/* Use double word type when available. */
+# define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ do { \
+ UDWtype __audw = (ah); \
+ UDWtype __budw = (bh); \
+ __audw <<= W_TYPE_SIZE; \
+ __audw |= (al); \
+ __budw <<= W_TYPE_SIZE; \
+ __budw |= (bl); \
+ __audw -= __budw; \
+ (sh) = (UWtype)(__audw >> W_TYPE_SIZE); \
+ (sl) = (UWtype)(__audw); \
+ } while (0)
+#elif !defined (sub_ddmmss)
# define sub_ddmmss(sh, sl, ah, al, bh, bl) \
do { \
UWtype __x; \
@@ -1637,7 +1675,15 @@ typedef unsigned int UTItype __attribute__ ((mode (TI)));
} while (0)
#endif
-#if !defined (umul_ppmm)
+#if !defined (umul_ppmm) && defined (UDWtype)
+# define umul_ppmm(w1, w0, u, v) \
+ do { \
+ UDWtype __x = (u); \
+ __x *= (v); \
+ (w1) = (UWtype)(__x >> W_TYPE_SIZE); \
+ (w0) = (UWtype)(__x); \
+ } while (0)
+#elif !defined (umul_ppmm)
# define umul_ppmm(w1, w0, u, v) \
do { \
UWtype __x0, __x1, __x2, __x3; \
@@ -1712,6 +1758,19 @@ typedef unsigned int UTItype __attribute__ ((mode (TI)));
(r) = __r0; \
} while (0)
+/* Use double word type if available. */
+#if !defined (udiv_qrnnd) && defined (UDWtype)
+# define udiv_qrnnd(q, r, nh, nl, d) \
+ do { \
+ UWtype __d = (d); \
+ UDWtype __nudw = (nh); \
+ __nudw <<= W_TYPE_SIZE; \
+ __nudw |= (nl); \
+ (q) = (UWtype)(__nudw / __d); \
+ (r) = (UWtype)(__nudw % __d); \
+ } while (0)
+#endif
+
/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through
__udiv_w_sdiv (defined in libgcc or elsewhere). */
#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd)
--
2.34.1
More information about the Gcrypt-devel
mailing list