arm_adi_v5: fix SIGSEGV due to failing re-examine
[openocd.git] / src / helper / bits.h
blob4e2a3456cf3823e712fdc33cb487f49f320a59e6
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 /*
4 * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
5 * Author(s): Antonio Borneo <borneo.antonio@gmail.com> for STMicroelectronics
6 */
8 /*
9 * The content of this file is mainly copied/inspired from Linux kernel
10 * code in include/linux/types.h include/linux/bitmap.h include/linux/bitops.h
13 #ifndef OPENOCD_HELPER_BITS_H
14 #define OPENOCD_HELPER_BITS_H
16 #include <helper/replacements.h>
17 #include <helper/types.h>
19 #define BIT(nr) (1UL << (nr))
20 #define BIT_ULL(nr) (1ULL << (nr))
21 #define BITS_PER_BYTE 8
22 #define BITS_PER_LONG (BITS_PER_BYTE * sizeof(long))
23 #define BITS_PER_LONG_LONG (BITS_PER_BYTE * sizeof(long long))
24 #define GENMASK(h, l) (((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h))))
25 #define GENMASK_ULL(h, l) (((~0ULL) - (1ULL << (l)) + 1) & (~0ULL >> (BITS_PER_LONG_LONG - 1 - (h))))
26 #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
27 #define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
28 #define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
29 #define DECLARE_BITMAP(name, bits) unsigned long name[BITS_TO_LONGS(bits)]
31 /**
32 * bitmap_zero - Clears all the bits in memory
33 * @param dst the address of the bitmap
34 * @param nbits the number of bits to clear
36 static inline void bitmap_zero(unsigned long *dst, unsigned int nbits)
38 unsigned int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
39 memset(dst, 0, len);
42 /**
43 * clear_bit - Clear a bit in memory
44 * @param nr the bit to set
45 * @param addr the address to start counting from
47 static inline void clear_bit(unsigned int nr, volatile unsigned long *addr)
49 unsigned long mask = BIT_MASK(nr);
50 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
52 *p &= ~mask;
55 /**
56 * set_bit - Set a bit in memory
57 * @param nr the bit to set
58 * @param addr the address to start counting from
60 static inline void set_bit(unsigned int nr, volatile unsigned long *addr)
62 unsigned long mask = BIT_MASK(nr);
63 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
65 *p |= mask;
68 /**
69 * test_bit - Determine whether a bit is set
70 * @param nr bit number to test
71 * @param addr Address to start counting from
73 static inline int test_bit(unsigned int nr, const volatile unsigned long *addr)
75 return 1UL & (addr[BIT_WORD(nr)] >> (nr % BITS_PER_LONG));
78 #endif /* OPENOCD_HELPER_BITS_H */