diff options
Diffstat (limited to 'vere/ext/nasm/include/ilog2.h')
-rw-r--r-- | vere/ext/nasm/include/ilog2.h | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/vere/ext/nasm/include/ilog2.h b/vere/ext/nasm/include/ilog2.h new file mode 100644 index 0000000..bba4595 --- /dev/null +++ b/vere/ext/nasm/include/ilog2.h @@ -0,0 +1,201 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2017 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ----------------------------------------------------------------------- */ + +#ifndef ILOG2_H +#define ILOG2_H + +#include "compiler.h" + +#ifdef ILOG2_C /* For generating the out-of-line functions */ +# undef extern_inline +# define extern_inline +# define inline_prototypes +#endif + +#ifdef inline_prototypes +extern unsigned int const_func ilog2_32(uint32_t v); +extern unsigned int const_func ilog2_64(uint64_t v); +extern unsigned int const_func ilog2_64(uint64_t vv); +extern int const_func alignlog2_32(uint32_t v); +extern int const_func alignlog2_64(uint64_t v); +#endif + +#ifdef extern_inline + +#define ROUND(v, a, w) \ + do { \ + if (v & (((UINT32_C(1) << w) - 1) << w)) { \ + a += w; \ + v >>= w; \ + } \ + } while (0) + + +#if defined(HAVE___BUILTIN_CLZ) && INT_MAX == 2147483647 + +extern_inline unsigned int const_func ilog2_32(uint32_t v) +{ + if (!v) + return 0; + + return __builtin_clz(v) ^ 31; +} + +#elif defined(__GNUC__) && defined(__x86_64__) + +extern_inline unsigned int const_func ilog2_32(uint32_t v) +{ + unsigned int n; + + __asm__("bsrl %1,%0" + : "=r" (n) + : "rm" (v), "0" (0)); + return n; +} + +#elif defined(__GNUC__) && defined(__i386__) + +extern_inline unsigned int const_func ilog2_32(uint32_t v) +{ + unsigned int n; + +#ifdef __i686__ + __asm__("bsrl %1,%0 ; cmovz %2,%0\n" + : "=&r" (n) + : "rm" (v), "r" (0)); +#else + __asm__("bsrl %1,%0 ; jnz 1f ; xorl %0,%0\n" + "1:" + : "=&r" (n) + : "rm" (v)); +#endif + return n; +} + +#elif defined(HAVE__BITSCANREVERSE) + +extern_inline unsigned int const_func ilog2_32(uint32_t v) +{ + unsigned long ix; + return _BitScanReverse(&ix, v) ? v : 0; +} + +#else + +extern_inline unsigned int const_func ilog2_32(uint32_t v) +{ + unsigned int p = 0; + + ROUND(v, p, 16); + ROUND(v, p, 8); + ROUND(v, p, 4); + ROUND(v, p, 2); + ROUND(v, p, 1); + + return p; +} + +#endif + +#if defined(HAVE__BUILTIN_CLZLL) && LLONG_MAX == 9223372036854775807LL + +extern_inline unsigned int const_func ilog2_64(uint64_t v) +{ + if (!v) + return 0; + + return __builtin_clzll(v) ^ 63; +} + +#elif defined(__GNUC__) && defined(__x86_64__) + +extern_inline unsigned int const_func ilog2_64(uint64_t v) +{ + uint64_t n; + + __asm__("bsrq %1,%0" + : "=r" (n) + : "rm" (v), "0" (UINT64_C(0))); + return n; +} + +#elif defined(HAVE__BITSCANREVERSE64) + +extern_inline unsigned int const_func ilog2_64(uint64_t v) +{ + unsigned long ix; + return _BitScanReverse64(&ix, v) ? ix : 0; +} + +#else + +extern_inline unsigned int const_func ilog2_64(uint64_t vv) +{ + unsigned int p = 0; + uint32_t v; + + v = vv >> 32; + if (v) + p += 32; + else + v = vv; + + return p + ilog2_32(v); +} + +#endif + +/* + * v == 0 ? 0 : is_power2(x) ? ilog2_X(v) : -1 + */ +extern_inline int const_func alignlog2_32(uint32_t v) +{ + if (unlikely(v & (v-1))) + return -1; /* invalid alignment */ + + return ilog2_32(v); +} + +extern_inline int const_func alignlog2_64(uint64_t v) +{ + if (unlikely(v & (v-1))) + return -1; /* invalid alignment */ + + return ilog2_64(v); +} + +#undef ROUND + +#endif /* extern_inline */ + +#endif /* ILOG2_H */ |