| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452 |
- /*
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2022-03-16 tyx first implementation
- */
- #ifndef CB_BITOPT_H_
- #define CB_BITOPT_H_
- #include "cb_def.h"
- #include <stdint.h>
- #ifdef __cplusplus
- extern "C" {
- #endif
- cb_inline void *cb_setbit(void *addr, unsigned int n)
- {
- cb_uint8_t *ptr = (cb_uint8_t *)addr;
- ptr[n / 8] |= 0x1 << n % 8;
- return addr;
- }
- cb_inline void *cb_clearbit(void *addr, unsigned int n)
- {
- cb_uint8_t *ptr = (cb_uint8_t *)addr;
- ptr[n / 8] &= ~(0x1 << n % 8);
- return addr;
- }
- cb_inline int cb_testbit(void *addr, unsigned int n)
- {
- cb_uint8_t *ptr = (cb_uint8_t *)addr;
- return !!(ptr[n / 8] & (0x1 << n % 8));
- }
- /**
- * @brief Find First bit Set in word(From LSB to MSB).
- * BIT counts from 0 and ranges from [0-31].
- * When the input value is 0x1, the return value is 0
- * When the input value is 0x2, the return value is 1
- * When the input value is 0x80000000, the return value is 31
- * When the input value is 0, the return value is also 0
- */
- cb_inline int cb_ffs32(cb_uint32_t x)
- {
- int r = 0;
- if (x)
- {
- if (!(x & 0xFFFFU))
- {
- x >>= 16;
- r += 16;
- }
- if (!(x & 0xFFU))
- {
- x >>= 8;
- r += 8;
- }
- if (!(x & 0xFU))
- {
- x >>= 4;
- r += 4;
- }
- if (!(x & 0x3U))
- {
- x >>= 2;
- r += 2;
- }
- if (!(x & 0x1U))
- {
- x >>= 1;
- r += 1;
- }
- }
- return r;
- }
- /**
- * @brief Find First bit Set in word(From LSB to MSB).
- * BIT counts from 0 and ranges from [0-63].
- * When the input value is 0x1, the return value is 0
- * When the input value is 0x2, the return value is 1
- * When the input value is 0x8000000000000000, the return value is 63
- * When the input value is 0, the return value is also 0
- */
- cb_inline int cb_ffs64(cb_uint64_t x)
- {
- int r = 0;
- if (x)
- {
- if (!(x & 0xFFFFFFFFULL))
- {
- x >>= 32;
- r += 32;
- }
- if (!(x & 0xFFFFULL))
- {
- x >>= 16;
- r += 16;
- }
- if (!(x & 0xFFULL))
- {
- x >>= 8;
- r += 8;
- }
- if (!(x & 0xFULL))
- {
- x >>= 4;
- r += 4;
- }
- if (!(x & 0x3ULL))
- {
- x >>= 2;
- r += 2;
- }
- if (!(x & 0x1ULL))
- {
- x >>= 1;
- r += 1;
- }
- }
- return r;
- }
- /**
- * @brief Find First bit Set in word(From LSB to MSB).
- * If the value of *addr is 0, the return value is meaningless
- */
- cb_inline int cb_ffs(unsigned long x)
- {
- return cb_ffs64(x);
- }
- /**
- * @brief Find First zero in word(From LSB to MSB).
- * BIT counts from 0 and ranges from [0-31].
- * When the input value is 0x0, the return value is 0
- * When the input value is 0x1, the return value is 1
- * When the input value is 0x2, the return value is 0
- * When the input value is 0x000000FF, the return value is 8
- * When the input value is 0xFFFFFFFF, the return value is also 0
- */
- cb_inline int cb_ffz32(cb_uint32_t x)
- {
- return cb_ffs32(~x);
- }
- /**
- * @brief Find First zero in word(From LSB to MSB).
- * BIT counts from 0 and ranges from [0-63].
- * When the input value is 0x0, the return value is 0
- * When the input value is 0x1, the return value is 1
- * When the input value is 0x2, the return value is 0
- * When the input value is 0x00000000FFFFFFFF, the return value is 32
- * When the input value is 0xFFFFFFFFFFFFFFFF, the return value is also 0
- */
- cb_inline int cb_ffz64(cb_uint64_t x)
- {
- return cb_ffs64(~x);
- }
- /**
- * @brief Find First zero in word(From LSB to MSB).
- * If *addr is the maximum machine word length, the return value is meaningless
- */
- cb_inline int cb_ffz(unsigned long x)
- {
- cb_uint64_t mask = (~0x0ULL) ^ (~0x0UL);
- return cb_ffz64(mask | x);
- }
- /**
- * @brief Count Leading Zeroes.
- * The value ranges from 0 to 32
- * When the input value is 0x0, the return value is 32
- * When the input value is 0x1, the return value is 31
- * When the input value is 0x2, the return value is 30
- * When the input value is 0xF0, the return value is 24
- * When the input value is 0xFFFFFFFF, the return value is 0
- */
- cb_inline int cb_clz32(cb_uint32_t x)
- {
- int r = 0;
- if (x)
- {
- if (!(x & 0xFFFF0000U))
- {
- x <<= 16;
- r += 16;
- }
- if (!(x & 0xFF000000U))
- {
- x <<= 8;
- r += 8;
- }
- if (!(x & 0xF0000000U))
- {
- x <<= 4;
- r += 4;
- }
- if (!(x & 0xC0000000U))
- {
- x <<= 2;
- r += 2;
- }
- if (!(x & 0x80000000U))
- {
- x <<= 1;
- r += 1;
- }
- }
- else
- {
- r = 32;
- }
- return r;
- }
- /**
- * @brief Count Leading Zeroes.
- * The value ranges from 0 to 64
- * When the input value is 0x0, the return value is 64
- * When the input value is 0x1, the return value is 63
- * When the input value is 0x2, the return value is 62
- * When the input value is 0xF0, the return value is 56
- * When the input value is 0x00000000FFFFFFFF, the return value is 32
- * When the input value is 0xFFFFFFFFFFFFFFFF, the return value is 0
- */
- cb_inline int cb_clz64(cb_uint64_t x)
- {
- int r = 0;
- if (x)
- {
- if (!(x & 0xFFFFFFFF00000000ULL))
- {
- x <<= 32;
- r += 32;
- }
- if (!(x & 0xFFFF000000000000ULL))
- {
- x <<= 16;
- r += 16;
- }
- if (!(x & 0xFF00000000000000ULL))
- {
- x <<= 8;
- r += 8;
- }
- if (!(x & 0xF000000000000000ULL))
- {
- x <<= 4;
- r += 4;
- }
- if (!(x & 0xC000000000000000ULL))
- {
- x <<= 2;
- r += 2;
- }
- if (!(x & 0x8000000000000000ULL))
- {
- x <<= 1;
- r += 1;
- }
- }
- else
- {
- r = 64;
- }
- return r;
- }
- /**
- * @brief Count Leading Zeroes.
- */
- cb_inline int cb_clz(unsigned long x)
- {
- cb_uint64_t t = x;
- cb_uint64_t mask = ~0x0ULL;
- mask = mask << (sizeof(cb_uint64_t) * 8U - CB_BITS_LONG);
- mask = ~mask;
- t = t << (sizeof(cb_uint64_t) * 8U - CB_BITS_LONG);
- t |= mask;
- return cb_clz64(t);
- }
- /**
- * @brief Find Last bit set
- * The value ranges from 0 to 32
- * When the input value is 0x0, the return value is 0
- * When the input value is 0x1, the return value is 1
- * When the input value is 0xF0, the return value is 8
- * When the input value is 0x80000000, the return value is 32
- * When the input value is 0x80000001, the return value is 32
- */
- cb_inline int cb_fls32(cb_uint32_t x)
- {
- return 32 - cb_clz32(x);
- }
- /**
- * @brief Find Last bit set
- * The value ranges from 0 to 64
- * When the input value is 0x0, the return value is 0
- * When the input value is 0x1, the return value is 1
- * When the input value is 0xF0, the return value is 8
- * When the input value is 0x80000000, the return value is 32
- * When the input value is 0x8000000000000000, the return value is 64
- * When the input value is 0x8000000000000001, the return value is 64
- */
- cb_inline int cb_fls64(cb_uint64_t x)
- {
- return 64 - cb_clz64(x);
- }
- /**
- * @brief Find Last bit set
- */
- cb_inline int cb_fls(unsigned long x)
- {
- return CB_BITS_LONG - cb_clz(x);
- }
- /**
- * @brief Count Trailing Zeroes
- * The value ranges from 0 to 32
- * When the input value is 0x0, the return value is 32
- * When the input value is 0x2, the return value is 1
- * When the input value is 0x80000000, the return value is 31
- * When the input value is 0xFFFFFFFF, the return value is 0
- */
- cb_inline int cb_ctz32(cb_uint32_t x)
- {
- int r;
- if (x != 0)
- {
- r = cb_ffs32(x);
- }
- else
- {
- r = 32;
- }
- return r;
- }
- /**
- * @brief Count Trailing Zeroes
- * The value ranges from 0 to 64
- * When the input value is 0x0, the return value is 64
- * When the input value is 0x2, the return value is 1
- * When the input value is 0x3, the return value is 0
- * When the input value is 0x80000000, the return value is 31
- * When the input value is 0xFFFFFFFFFFFFFFFF, the return value is 0
- */
- cb_inline int cb_ctz64(cb_uint64_t x)
- {
- int r;
- if (x != 0)
- {
- r = cb_ffs64(x);
- }
- else
- {
- r = 64;
- }
- return r;
- }
- /**
- * @brief Count Trailing Zeroes
- */
- cb_inline int cb_ctz(unsigned long x)
- {
- int r;
- if (x != 0)
- {
- r = cb_ffs(x);
- }
- else
- {
- r = CB_BITS_LONG;
- }
- return r;
- }
- /**
- * @brief Finds the location of the first set from a section of memory
- */
- cb_inline unsigned long cb_find_next_bit(const unsigned long* addr,
- unsigned long size, unsigned long offset)
- {
- unsigned long res = size;
- unsigned long unalign_size, value = 0;
- unsigned long pos = offset;
- if (offset < size)
- {
- pos = offset;
- addr += offset / CB_BITS_LONG;
- unalign_size = offset % CB_BITS_LONG;
- // Head alignment processing
- value = (*addr++) >> unalign_size;
- offset += CB_BITS_LONG - unalign_size;
- if (offset > size)
- {
- offset = size;
- }
- // find
- while (value == 0 && offset < size)
- {
- value = *addr++;
- pos = offset;
- offset += CB_BITS_LONG;
- }
- // Tail alignment processing
- if (offset > size)
- {
- value = value & (~0x0UL >> (offset - size));
- }
- if (value != 0)
- {
- res = pos + cb_ffs(value);
- }
- }
- return res;
- }
- cb_inline unsigned long cb_find_first_bit(const unsigned long* addr,
- unsigned long size)
- {
- return cb_find_next_bit(addr, size, 0);
- }
- #define cb_for_each_set_bit(bit, addr, size) \
- for ((bit) = cb_find_first_bit(addr, size); (bit) < (size); \
- (bit) = cb_find_next_bit(addr, size, (bit) + 1))
- #ifdef __cplusplus
- }
- #endif
- #endif /* CB_BITOPT_H_ */
|