diff --git a/core/bitarithm.c b/core/bitarithm.c index f7fa213bafe14d5e307c90050ed163260fd7af7d..816f0891f0cb1cac7715f944a3c6306ed6b21ede 100644 --- a/core/bitarithm.c +++ b/core/bitarithm.c @@ -21,6 +21,8 @@ #include <stdio.h> +#include "bitarithm.h" + unsigned bitarithm_msb(unsigned v) { register unsigned r; // result of log2(v) will go here @@ -43,19 +45,7 @@ unsigned bitarithm_msb(unsigned v) return r; } -/*---------------------------------------------------------------------------*/ -unsigned bitarithm_lsb(register unsigned v) -{ - register unsigned r = 0; - - while ((v & 0x01) == 0) { - v >>= 1; - r++; - }; - return r; -} -/*---------------------------------------------------------------------------*/ unsigned bitarithm_bits_set(unsigned v) { unsigned c; // c accumulates the total bits set in v @@ -66,3 +56,9 @@ unsigned bitarithm_bits_set(unsigned v) return c; } + +const uint8_t MultiplyDeBruijnBitPosition[32] = +{ + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 +}; diff --git a/core/include/bitarithm.h b/core/include/bitarithm.h index bd2c6e5f14b402ffd7b5f2945fa2528d88368c13..bebdb3e405560983f1e5fcedba370a6189a409c5 100644 --- a/core/include/bitarithm.h +++ b/core/include/bitarithm.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2014 Freie Universität Berlin + * Copyright (C) 2017 Kaspar Schleiser <kaspar@schleiser.de> + * 2014 Freie Universität Berlin * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level @@ -20,6 +21,10 @@ #ifndef BITARITHM_H #define BITARITHM_H +#include <stdint.h> + +#include "cpu_conf.h" + #ifdef __cplusplus extern "C" { #endif @@ -105,19 +110,44 @@ unsigned bitarithm_msb(unsigned v); * function will produce an infinite loop * @return Bit Number * - * Source: http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious */ -unsigned bitarithm_lsb(register unsigned v); +static inline unsigned bitarithm_lsb(unsigned v); /** * @brief Returns the number of bits set in a value * @param[in] v Input value * @return Number of set bits * - * Source: http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious */ unsigned bitarithm_bits_set(unsigned v); +/* implementations */ + +static inline unsigned bitarithm_lsb(unsigned v) +#if defined(BITARITHM_LSB_BUILTIN) +{ + return __builtin_ffs(v) - 1; +} +#elif defined(BITARITHM_LSB_LOOKUP) +{ +/* Source: http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup */ + extern const uint8_t MultiplyDeBruijnBitPosition[32]; + return MultiplyDeBruijnBitPosition[((uint32_t)((v & -v) * 0x077CB531U)) >> 27]; +} +#else +{ +/* Source: http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious */ + unsigned r = 0; + + while ((v & 0x01) == 0) { + v >>= 1; + r++; + }; + + return r; +} +#endif + #ifdef __cplusplus } #endif diff --git a/cpu/cortexm_common/include/cpu_conf_common.h b/cpu/cortexm_common/include/cpu_conf_common.h index 8d2d17744e14ca27cf34993a9f430fca2348b130..513d53da09557ec942e02006cc295880a0f1765f 100644 --- a/cpu/cortexm_common/include/cpu_conf_common.h +++ b/cpu/cortexm_common/include/cpu_conf_common.h @@ -57,6 +57,17 @@ extern "C" { #endif /** @} */ +/** + * @brief Select fastest bitarithm_lsb implementation + * @{ + */ +#ifdef __ARM_FEATURE_CLZ +#define BITARITHM_LSB_BUILTIN +#else +#define BITARITHM_LSB_LOOKUP +#endif +/** @} */ + #ifdef __cplusplus } #endif