[PATCH 2/6] bithelp: add count trailing zero bits variant for RISC-V
Jussi Kivilinna
jussi.kivilinna at iki.fi
Mon Jan 6 16:08:49 CET 2025
* cipher/bithelp.h (_gcry_ctz_no_zero): New.
(_gcry_ctz): Use '_gcry_ctz_no_zero'.
* cipher/cipher-internal.h (ocb_get_l): Use '_gcry_ctz_no_zero'.
--
Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
cipher/bithelp.h | 33 ++++++++++++++++++++++++++++-----
cipher/cipher-internal.h | 2 +-
2 files changed, 29 insertions(+), 6 deletions(-)
diff --git a/cipher/bithelp.h b/cipher/bithelp.h
index 7793ce7c..a4faf345 100644
--- a/cipher/bithelp.h
+++ b/cipher/bithelp.h
@@ -19,6 +19,7 @@
#ifndef GCRYPT_BITHELP_H
#define GCRYPT_BITHELP_H
+#include "config.h"
#include "types.h"
@@ -77,13 +78,25 @@ _gcry_bswap64(u64 x)
/* Count trailing zero bits in an unsigend int. We return an int
- because that is what gcc's builtin does. Returns the number of
- bits in X if X is 0. */
+ because that is what gcc's builtin does. X must not be zero. */
static inline int
-_gcry_ctz (unsigned int x)
+_gcry_ctz_no_zero (unsigned int x)
{
-#if defined (HAVE_BUILTIN_CTZ)
- return x ? __builtin_ctz (x) : 8 * sizeof (x);
+#if defined(__riscv) && \
+ (defined(__riscv_f) && __riscv_f >= 2002000) && \
+ (!defined(__riscv_zbb) || __riscv_zbb < 2002000) && \
+ defined(HAVE_GCC_ATTRIBUTE_MAY_ALIAS)
+ /* Use float cast approach when building for RISC-V without Zbb extension.
+ * Without Zbb, GCC gives us slower generic version for __builtin_ctz().
+ *
+ * See:
+ * http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightFloatCast
+ */
+ float f = (float)(x & -x);
+ typedef u32 __attribute__((may_alias)) may_alias_u32;
+ return ((*(const may_alias_u32 *)&f) >> 23) - 0x7f;
+#elif defined (HAVE_BUILTIN_CTZ)
+ return __builtin_ctz (x);
#else
/* See
* http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightModLookup
@@ -100,6 +113,16 @@ _gcry_ctz (unsigned int x)
}
+/* Count trailing zero bits in an unsigend int. We return an int
+ because that is what gcc's builtin does. Returns the number of
+ bits in X if X is 0. */
+static inline int
+_gcry_ctz (unsigned int x)
+{
+ return x ? _gcry_ctz_no_zero (x) : 8 * sizeof (x);
+}
+
+
/* Count trailing zero bits in an u64. We return an int because that
is what gcc's builtin does. Returns the number of bits in X if X
is 0. */
diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h
index ddf8fbb5..19b3eada 100644
--- a/cipher/cipher-internal.h
+++ b/cipher/cipher-internal.h
@@ -775,7 +775,7 @@ ocb_get_l (gcry_cipher_hd_t c, u64 n)
: [low] "r" ((unsigned long)n)
: "cc");
#else
- ntz = _gcry_ctz (n);
+ ntz = _gcry_ctz_no_zero (n);
#endif
return c->u_mode.ocb.L[ntz];
--
2.45.2
More information about the Gcrypt-devel
mailing list