[PATCH 2/6] bithelp: add count trailing zero bits variant for RISC-V

Jussi Kivilinna <[email protected]>
Newsgroups gmane.comp.encryption.gpg.libgcrypt.devel
Message-ID <[email protected]>
* 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 <[email protected]>
---
 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.