Commit 8850f303 authored by Ben Avison's avatar Ben Avison
Browse files

Add versions of clz (and family) suitable for inlining into C

parent 3d66cea8
Pipeline #6135 passed with stages
in 21 seconds
......@@ -28,6 +28,94 @@
extern "C" {
#endif
#if defined(__aarch64__) || ((defined(__arm__) || defined(__arm)) && defined(__ARM_FEATURE_CLZ))
/* Versions of the functions suitable for inlining */
/* Returns the number of leading zero bits in the argument, 0 ... 32 */
static inline unsigned int clz(unsigned int value)
{
unsigned int leading_zeros;
#ifdef __GNUC__
#ifdef __aarch64__
__asm("clz %w[leading_zeros], %w[value]"
#else
__asm("clz %[leading_zeros], %[value]"
#endif
: [leading_zeros]"=r"(leading_zeros)
: [value]"r"(value));
#else
__asm { CLZ leading_zeros, value }
#endif
return leading_zeros;
}
/* Returns the number of trailing zero bits in the argument, 0 ... 32 */
static inline unsigned int ctz(unsigned int value)
{
if (value == 0)
return 32;
return 31 - clz(value &~ (value - 1));
}
/* Returns the number of leading one bits in the argument, 0 ... 32 */
static inline unsigned int clo(unsigned int value)
{
return clz(~value);
}
/* Returns the number of trailing one bits in the argument, 0 ... 32 */
static inline unsigned int cto(unsigned int value)
{
return ctz(~value);
}
/* Returns the number of leading zero bits in the argument, 0 ... 64 */
static inline unsigned int clz64(unsigned long long value)
{
unsigned int extra_zeros = 0, leading_zeros;
#if defined(__GNUC__) && defined(__aarch64__)
__asm("clz %[leading_zeros], %[value]"
: [leading_zeros]"=r"(leading_zeros)
: [value]"r"(value));
#else
if (value &~ 0xFFFFFFFFull)
value >>= 32;
else
extra_zeros = 32;
#if defined(__GNUC__)
__asm("clz %[leading_zeros], %[value]"
: [leading_zeros]"=r"(leading_zeros)
: [value]"r"((unsigned int) value));
#else
__asm { CLZ leading_zeros, (unsigned int) value }
#endif
#endif
return extra_zeros + leading_zeros;
}
/* Returns the number of trailing zero bits in the argument, 0 ... 64 */
static inline unsigned int ctz64(unsigned long long value)
{
if (value == 0)
return 64;
return 63 - clz64(value &~ (value - 1));
}
/* Returns the number of leading one bits in the argument, 0 ... 64 */
static inline unsigned int clo64(unsigned long long value)
{
return clz64(~value);
}
/* Returns the number of trailing one bits in the argument, 0 ... 64 */
static inline unsigned int cto64(unsigned long long value)
{
return ctz64(~value);
}
#else
/* These functions adapt to be optimal for CPUs with or without the CLZ instruction */
extern unsigned int clz(unsigned int);
......@@ -54,6 +142,8 @@ extern unsigned int clo64(unsigned long long);
extern unsigned int cto64(unsigned long long);
/* Returns the number of trailing one bits in the argument, 0 ... 64 */
#endif
#ifdef __cplusplus
}
#endif
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment