xref: /dpdk/lib/eal/include/rte_bitops.h (revision 21cab84f6f8c946fabf72fdb03ce4b274887b950)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(c) 2020 Arm Limited
3916c50ddSTyler Retzlaff  * Copyright(c) 2010-2019 Intel Corporation
4916c50ddSTyler Retzlaff  * Copyright(c) 2023 Microsoft Corporation
5471de107SMattias Rönnblom  * Copyright(c) 2024 Ericsson AB
699a2dd95SBruce Richardson  */
799a2dd95SBruce Richardson 
899a2dd95SBruce Richardson #ifndef _RTE_BITOPS_H_
999a2dd95SBruce Richardson #define _RTE_BITOPS_H_
1099a2dd95SBruce Richardson 
1199a2dd95SBruce Richardson /**
1299a2dd95SBruce Richardson  * @file
1399a2dd95SBruce Richardson  * Bit Operations
1499a2dd95SBruce Richardson  *
15471de107SMattias Rönnblom  * This file provides functionality for low-level, single-word
16471de107SMattias Rönnblom  * arithmetic and bit-level operations, such as counting or
17471de107SMattias Rönnblom  * setting individual bits.
1899a2dd95SBruce Richardson  */
1999a2dd95SBruce Richardson 
2099a2dd95SBruce Richardson #include <stdint.h>
2130764c0fSStephen Hemminger 
22471de107SMattias Rönnblom #include <rte_compat.h>
2399a2dd95SBruce Richardson #include <rte_debug.h>
2435326b61SMattias Rönnblom #include <rte_stdatomic.h>
2599a2dd95SBruce Richardson 
26d7e9c02cSBrian Dooley #ifdef __cplusplus
27d7e9c02cSBrian Dooley extern "C" {
28d7e9c02cSBrian Dooley #endif
29d7e9c02cSBrian Dooley 
3099a2dd95SBruce Richardson /**
3199a2dd95SBruce Richardson  * Get the uint64_t value for a specified bit set.
3299a2dd95SBruce Richardson  *
3399a2dd95SBruce Richardson  * @param nr
3499a2dd95SBruce Richardson  *   The bit number in range of 0 to 63.
3599a2dd95SBruce Richardson  */
3699a2dd95SBruce Richardson #define RTE_BIT64(nr) (UINT64_C(1) << (nr))
3799a2dd95SBruce Richardson 
3899a2dd95SBruce Richardson /**
3999a2dd95SBruce Richardson  * Get the uint32_t value for a specified bit set.
4099a2dd95SBruce Richardson  *
4199a2dd95SBruce Richardson  * @param nr
4299a2dd95SBruce Richardson  *   The bit number in range of 0 to 31.
4399a2dd95SBruce Richardson  */
4499a2dd95SBruce Richardson #define RTE_BIT32(nr) (UINT32_C(1) << (nr))
4599a2dd95SBruce Richardson 
461d8f2285SChengwen Feng /**
471d8f2285SChengwen Feng  * Get the uint32_t shifted value.
481d8f2285SChengwen Feng  *
491d8f2285SChengwen Feng  * @param val
501d8f2285SChengwen Feng  *   The value to be shifted.
511d8f2285SChengwen Feng  * @param nr
521d8f2285SChengwen Feng  *   The shift number in range of 0 to (32 - width of val).
531d8f2285SChengwen Feng  */
541d8f2285SChengwen Feng #define RTE_SHIFT_VAL32(val, nr) (UINT32_C(val) << (nr))
551d8f2285SChengwen Feng 
561d8f2285SChengwen Feng /**
571d8f2285SChengwen Feng  * Get the uint64_t shifted value.
581d8f2285SChengwen Feng  *
591d8f2285SChengwen Feng  * @param val
601d8f2285SChengwen Feng  *   The value to be shifted.
611d8f2285SChengwen Feng  * @param nr
621d8f2285SChengwen Feng  *   The shift number in range of 0 to (64 - width of val).
631d8f2285SChengwen Feng  */
641d8f2285SChengwen Feng #define RTE_SHIFT_VAL64(val, nr) (UINT64_C(val) << (nr))
651d8f2285SChengwen Feng 
661d8f2285SChengwen Feng /**
671d8f2285SChengwen Feng  * Generate a contiguous 32-bit mask
681d8f2285SChengwen Feng  * starting at bit position low and ending at position high.
691d8f2285SChengwen Feng  *
701d8f2285SChengwen Feng  * @param high
711d8f2285SChengwen Feng  *   High bit position.
721d8f2285SChengwen Feng  * @param low
731d8f2285SChengwen Feng  *   Low bit position.
741d8f2285SChengwen Feng  */
751d8f2285SChengwen Feng #define RTE_GENMASK32(high, low) \
761d8f2285SChengwen Feng 		(((~UINT32_C(0)) << (low)) & (~UINT32_C(0) >> (31u - (high))))
771d8f2285SChengwen Feng 
781d8f2285SChengwen Feng /**
791d8f2285SChengwen Feng  * Generate a contiguous 64-bit mask
801d8f2285SChengwen Feng  * starting at bit position low and ending at position high.
811d8f2285SChengwen Feng  *
821d8f2285SChengwen Feng  * @param high
831d8f2285SChengwen Feng  *   High bit position.
841d8f2285SChengwen Feng  * @param low
851d8f2285SChengwen Feng  *   Low bit position.
861d8f2285SChengwen Feng  */
871d8f2285SChengwen Feng #define RTE_GENMASK64(high, low) \
881d8f2285SChengwen Feng 		(((~UINT64_C(0)) << (low)) & (~UINT64_C(0) >> (63u - (high))))
891d8f2285SChengwen Feng 
901d8f2285SChengwen Feng /**
911d8f2285SChengwen Feng  * Extract a 32-bit field element.
921d8f2285SChengwen Feng  *
931d8f2285SChengwen Feng  * @param mask
941d8f2285SChengwen Feng  *   Shifted mask.
951d8f2285SChengwen Feng  * @param reg
961d8f2285SChengwen Feng  *   Value of entire bitfield.
971d8f2285SChengwen Feng  */
981d8f2285SChengwen Feng #define RTE_FIELD_GET32(mask, reg) \
991d8f2285SChengwen Feng 		((typeof(mask))(((reg) & (mask)) >> rte_ctz32(mask)))
1001d8f2285SChengwen Feng 
1011d8f2285SChengwen Feng /**
1021d8f2285SChengwen Feng  * Extract a 64-bit field element.
1031d8f2285SChengwen Feng  *
1041d8f2285SChengwen Feng  * @param mask
1051d8f2285SChengwen Feng  *   Shifted mask.
1061d8f2285SChengwen Feng  * @param reg
1071d8f2285SChengwen Feng  *   Value of entire bitfield.
1081d8f2285SChengwen Feng  */
1091d8f2285SChengwen Feng #define RTE_FIELD_GET64(mask, reg) \
1101d8f2285SChengwen Feng 		((typeof(mask))(((reg) & (mask)) >> rte_ctz64(mask)))
1111d8f2285SChengwen Feng 
112471de107SMattias Rönnblom /**
113471de107SMattias Rönnblom  * @warning
114471de107SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
115471de107SMattias Rönnblom  *
116471de107SMattias Rönnblom  * Test bit in word.
117471de107SMattias Rönnblom  *
118471de107SMattias Rönnblom  * Generic selection macro to test the value of a bit in a 32-bit or
119471de107SMattias Rönnblom  * 64-bit word. The type of operation depends on the type of the @c
120471de107SMattias Rönnblom  * addr parameter.
121471de107SMattias Rönnblom  *
122471de107SMattias Rönnblom  * This macro does not give any guarantees in regards to memory
123471de107SMattias Rönnblom  * ordering or atomicity.
124471de107SMattias Rönnblom  *
125471de107SMattias Rönnblom  * @param addr
126471de107SMattias Rönnblom  *   A pointer to the word to modify.
127471de107SMattias Rönnblom  * @param nr
128471de107SMattias Rönnblom  *   The index of the bit.
129471de107SMattias Rönnblom  */
130471de107SMattias Rönnblom #define rte_bit_test(addr, nr) \
131471de107SMattias Rönnblom 	_Generic((addr), \
132471de107SMattias Rönnblom 		uint32_t *: __rte_bit_test32, \
133471de107SMattias Rönnblom 		const uint32_t *: __rte_bit_test32, \
1340883d736SMattias Rönnblom 		volatile uint32_t *: __rte_bit_v_test32, \
1350883d736SMattias Rönnblom 		const volatile uint32_t *: __rte_bit_v_test32, \
136471de107SMattias Rönnblom 		uint64_t *: __rte_bit_test64, \
1370883d736SMattias Rönnblom 		const uint64_t *: __rte_bit_test64, \
1380883d736SMattias Rönnblom 		volatile uint64_t *: __rte_bit_v_test64, \
1390883d736SMattias Rönnblom 		const volatile uint64_t *: __rte_bit_v_test64) \
140471de107SMattias Rönnblom 			(addr, nr)
141471de107SMattias Rönnblom 
142471de107SMattias Rönnblom /**
143471de107SMattias Rönnblom  * @warning
144471de107SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
145471de107SMattias Rönnblom  *
146471de107SMattias Rönnblom  * Set bit in word.
147471de107SMattias Rönnblom  *
148471de107SMattias Rönnblom  * Generic selection macro to set a bit in a 32-bit or 64-bit
149471de107SMattias Rönnblom  * word. The type of operation depends on the type of the @c addr
150471de107SMattias Rönnblom  * parameter.
151471de107SMattias Rönnblom  *
152471de107SMattias Rönnblom  * This macro does not give any guarantees in regards to memory
153471de107SMattias Rönnblom  * ordering or atomicity.
154471de107SMattias Rönnblom  *
155471de107SMattias Rönnblom  * @param addr
156471de107SMattias Rönnblom  *   A pointer to the word to modify.
157471de107SMattias Rönnblom  * @param nr
158471de107SMattias Rönnblom  *   The index of the bit.
159471de107SMattias Rönnblom  */
160471de107SMattias Rönnblom #define rte_bit_set(addr, nr) \
161471de107SMattias Rönnblom 	_Generic((addr), \
162471de107SMattias Rönnblom 		uint32_t *: __rte_bit_set32, \
1630883d736SMattias Rönnblom 		volatile uint32_t *: __rte_bit_v_set32, \
1640883d736SMattias Rönnblom 		uint64_t *: __rte_bit_set64, \
1650883d736SMattias Rönnblom 		volatile uint64_t *: __rte_bit_v_set64) \
166471de107SMattias Rönnblom 			(addr, nr)
167471de107SMattias Rönnblom 
168471de107SMattias Rönnblom /**
169471de107SMattias Rönnblom  * @warning
170471de107SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
171471de107SMattias Rönnblom  *
172471de107SMattias Rönnblom  * Clear bit in word.
173471de107SMattias Rönnblom  *
174471de107SMattias Rönnblom  * Generic selection macro to clear a bit in a 32-bit or 64-bit
175471de107SMattias Rönnblom  * word. The type of operation depends on the type of the @c addr
176471de107SMattias Rönnblom  * parameter.
177471de107SMattias Rönnblom  *
178471de107SMattias Rönnblom  * This macro does not give any guarantees in regards to memory
179471de107SMattias Rönnblom  * ordering or atomicity.
180471de107SMattias Rönnblom  *
181471de107SMattias Rönnblom  * @param addr
182471de107SMattias Rönnblom  *   A pointer to the word to modify.
183471de107SMattias Rönnblom  * @param nr
184471de107SMattias Rönnblom  *   The index of the bit.
185471de107SMattias Rönnblom  */
186471de107SMattias Rönnblom #define rte_bit_clear(addr, nr) \
187471de107SMattias Rönnblom 	_Generic((addr), \
188471de107SMattias Rönnblom 		uint32_t *: __rte_bit_clear32, \
1890883d736SMattias Rönnblom 		volatile uint32_t *: __rte_bit_v_clear32, \
1900883d736SMattias Rönnblom 		uint64_t *: __rte_bit_clear64, \
1910883d736SMattias Rönnblom 		volatile uint64_t *: __rte_bit_v_clear64) \
192471de107SMattias Rönnblom 			(addr, nr)
193471de107SMattias Rönnblom 
194471de107SMattias Rönnblom /**
195471de107SMattias Rönnblom  * @warning
196471de107SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
197471de107SMattias Rönnblom  *
198471de107SMattias Rönnblom  * Assign a value to a bit in word.
199471de107SMattias Rönnblom  *
200471de107SMattias Rönnblom  * Generic selection macro to assign a value to a bit in a 32-bit or 64-bit
201471de107SMattias Rönnblom  * word. The type of operation depends on the type of the @c addr parameter.
202471de107SMattias Rönnblom  *
203471de107SMattias Rönnblom  * This macro does not give any guarantees in regards to memory
204471de107SMattias Rönnblom  * ordering or atomicity.
205471de107SMattias Rönnblom  *
206471de107SMattias Rönnblom  * @param addr
207471de107SMattias Rönnblom  *   A pointer to the word to modify.
208471de107SMattias Rönnblom  * @param nr
209471de107SMattias Rönnblom  *   The index of the bit.
210471de107SMattias Rönnblom  * @param value
211471de107SMattias Rönnblom  *   The new value of the bit - true for '1', or false for '0'.
212471de107SMattias Rönnblom  */
213471de107SMattias Rönnblom #define rte_bit_assign(addr, nr, value) \
214471de107SMattias Rönnblom 	_Generic((addr), \
215471de107SMattias Rönnblom 		uint32_t *: __rte_bit_assign32, \
2160883d736SMattias Rönnblom 		volatile uint32_t *: __rte_bit_v_assign32, \
2170883d736SMattias Rönnblom 		uint64_t *: __rte_bit_assign64, \
2180883d736SMattias Rönnblom 		volatile uint64_t *: __rte_bit_v_assign64) \
219471de107SMattias Rönnblom 			(addr, nr, value)
220471de107SMattias Rönnblom 
221471de107SMattias Rönnblom /**
222471de107SMattias Rönnblom  * @warning
223471de107SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
224471de107SMattias Rönnblom  *
225471de107SMattias Rönnblom  * Flip a bit in word.
226471de107SMattias Rönnblom  *
227471de107SMattias Rönnblom  * Generic selection macro to change the value of a bit to '0' if '1'
228471de107SMattias Rönnblom  * or '1' if '0' in a 32-bit or 64-bit word. The type of operation
229471de107SMattias Rönnblom  * depends on the type of the @c addr parameter.
230471de107SMattias Rönnblom  *
231471de107SMattias Rönnblom  * This macro does not give any guarantees in regards to memory
232471de107SMattias Rönnblom  * ordering or atomicity.
233471de107SMattias Rönnblom  *
234471de107SMattias Rönnblom  * @param addr
235471de107SMattias Rönnblom  *   A pointer to the word to modify.
236471de107SMattias Rönnblom  * @param nr
237471de107SMattias Rönnblom  *   The index of the bit.
238471de107SMattias Rönnblom  */
239471de107SMattias Rönnblom #define rte_bit_flip(addr, nr) \
240471de107SMattias Rönnblom 	_Generic((addr), \
241471de107SMattias Rönnblom 		uint32_t *: __rte_bit_flip32, \
2420883d736SMattias Rönnblom 		volatile uint32_t *: __rte_bit_v_flip32, \
2430883d736SMattias Rönnblom 		uint64_t *: __rte_bit_flip64, \
2440883d736SMattias Rönnblom 		volatile uint64_t *: __rte_bit_v_flip64) \
245471de107SMattias Rönnblom 			(addr, nr)
246471de107SMattias Rönnblom 
24735326b61SMattias Rönnblom /**
24835326b61SMattias Rönnblom  * @warning
24935326b61SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
25035326b61SMattias Rönnblom  *
25135326b61SMattias Rönnblom  * Test if a particular bit in a word is set with a particular memory
25235326b61SMattias Rönnblom  * order.
25335326b61SMattias Rönnblom  *
25435326b61SMattias Rönnblom  * Test a bit with the resulting memory load ordered as per the
25535326b61SMattias Rönnblom  * specified memory order.
25635326b61SMattias Rönnblom  *
25735326b61SMattias Rönnblom  * @param addr
25835326b61SMattias Rönnblom  *   A pointer to the word to query.
25935326b61SMattias Rönnblom  * @param nr
26035326b61SMattias Rönnblom  *   The index of the bit.
26135326b61SMattias Rönnblom  * @param memory_order
26235326b61SMattias Rönnblom  *   The memory order to use.
26335326b61SMattias Rönnblom  * @return
26435326b61SMattias Rönnblom  *   Returns true if the bit is set, and false otherwise.
26535326b61SMattias Rönnblom  */
26635326b61SMattias Rönnblom #define rte_bit_atomic_test(addr, nr, memory_order) \
26735326b61SMattias Rönnblom 	_Generic((addr), \
26835326b61SMattias Rönnblom 		uint32_t *: __rte_bit_atomic_test32, \
26935326b61SMattias Rönnblom 		const uint32_t *: __rte_bit_atomic_test32, \
2700883d736SMattias Rönnblom 		volatile uint32_t *: __rte_bit_atomic_v_test32, \
2710883d736SMattias Rönnblom 		const volatile uint32_t *: __rte_bit_atomic_v_test32, \
27235326b61SMattias Rönnblom 		uint64_t *: __rte_bit_atomic_test64, \
2730883d736SMattias Rönnblom 		const uint64_t *: __rte_bit_atomic_test64, \
2740883d736SMattias Rönnblom 		volatile uint64_t *: __rte_bit_atomic_v_test64, \
2750883d736SMattias Rönnblom 		const volatile uint64_t *: __rte_bit_atomic_v_test64) \
27635326b61SMattias Rönnblom 			(addr, nr, memory_order)
27735326b61SMattias Rönnblom 
27835326b61SMattias Rönnblom /**
27935326b61SMattias Rönnblom  * @warning
28035326b61SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
28135326b61SMattias Rönnblom  *
28235326b61SMattias Rönnblom  * Atomically set bit in word.
28335326b61SMattias Rönnblom  *
28435326b61SMattias Rönnblom  * Generic selection macro to atomically set bit specified by @c nr in
28535326b61SMattias Rönnblom  * the word pointed to by @c addr to '1', with the memory ordering as
28635326b61SMattias Rönnblom  * specified by @c memory_order.
28735326b61SMattias Rönnblom  *
28835326b61SMattias Rönnblom  * @param addr
28935326b61SMattias Rönnblom  *   A pointer to the word to modify.
29035326b61SMattias Rönnblom  * @param nr
29135326b61SMattias Rönnblom  *   The index of the bit.
29235326b61SMattias Rönnblom  * @param memory_order
29335326b61SMattias Rönnblom  *   The memory order to use.
29435326b61SMattias Rönnblom  */
29535326b61SMattias Rönnblom #define rte_bit_atomic_set(addr, nr, memory_order) \
29635326b61SMattias Rönnblom 	_Generic((addr), \
29735326b61SMattias Rönnblom 		uint32_t *: __rte_bit_atomic_set32, \
2980883d736SMattias Rönnblom 		volatile uint32_t *: __rte_bit_atomic_v_set32, \
2990883d736SMattias Rönnblom 		uint64_t *: __rte_bit_atomic_set64, \
3000883d736SMattias Rönnblom 		volatile uint64_t *: __rte_bit_atomic_v_set64) \
30135326b61SMattias Rönnblom 			(addr, nr, memory_order)
30235326b61SMattias Rönnblom 
30335326b61SMattias Rönnblom /**
30435326b61SMattias Rönnblom  * @warning
30535326b61SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
30635326b61SMattias Rönnblom  *
30735326b61SMattias Rönnblom  * Atomically clear bit in word.
30835326b61SMattias Rönnblom  *
30935326b61SMattias Rönnblom  * Generic selection macro to atomically set bit specified by @c nr in
31035326b61SMattias Rönnblom  * the word pointed to by @c addr to '0', with the memory ordering as
31135326b61SMattias Rönnblom  * specified by @c memory_order.
31235326b61SMattias Rönnblom  *
31335326b61SMattias Rönnblom  * @param addr
31435326b61SMattias Rönnblom  *   A pointer to the word to modify.
31535326b61SMattias Rönnblom  * @param nr
31635326b61SMattias Rönnblom  *   The index of the bit.
31735326b61SMattias Rönnblom  * @param memory_order
31835326b61SMattias Rönnblom  *   The memory order to use.
31935326b61SMattias Rönnblom  */
32035326b61SMattias Rönnblom #define rte_bit_atomic_clear(addr, nr, memory_order) \
32135326b61SMattias Rönnblom 	_Generic((addr), \
32235326b61SMattias Rönnblom 		uint32_t *: __rte_bit_atomic_clear32, \
3230883d736SMattias Rönnblom 		volatile uint32_t *: __rte_bit_atomic_v_clear32, \
3240883d736SMattias Rönnblom 		uint64_t *: __rte_bit_atomic_clear64, \
3250883d736SMattias Rönnblom 		volatile uint64_t *: __rte_bit_atomic_v_clear64) \
32635326b61SMattias Rönnblom 			(addr, nr, memory_order)
32735326b61SMattias Rönnblom 
32835326b61SMattias Rönnblom /**
32935326b61SMattias Rönnblom  * @warning
33035326b61SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
33135326b61SMattias Rönnblom  *
33235326b61SMattias Rönnblom  * Atomically assign a value to bit in word.
33335326b61SMattias Rönnblom  *
33435326b61SMattias Rönnblom  * Generic selection macro to atomically set bit specified by @c nr in the
33535326b61SMattias Rönnblom  * word pointed to by @c addr to the value indicated by @c value, with
33635326b61SMattias Rönnblom  * the memory ordering as specified with @c memory_order.
33735326b61SMattias Rönnblom  *
33835326b61SMattias Rönnblom  * @param addr
33935326b61SMattias Rönnblom  *   A pointer to the word to modify.
34035326b61SMattias Rönnblom  * @param nr
34135326b61SMattias Rönnblom  *   The index of the bit.
34235326b61SMattias Rönnblom  * @param value
34335326b61SMattias Rönnblom  *   The new value of the bit - true for '1', or false for '0'.
34435326b61SMattias Rönnblom  * @param memory_order
34535326b61SMattias Rönnblom  *   The memory order to use.
34635326b61SMattias Rönnblom  */
34735326b61SMattias Rönnblom #define rte_bit_atomic_assign(addr, nr, value, memory_order) \
34835326b61SMattias Rönnblom 	_Generic((addr), \
34935326b61SMattias Rönnblom 		uint32_t *: __rte_bit_atomic_assign32, \
3500883d736SMattias Rönnblom 		volatile uint32_t *: __rte_bit_atomic_v_assign32, \
3510883d736SMattias Rönnblom 		uint64_t *: __rte_bit_atomic_assign64, \
3520883d736SMattias Rönnblom 		volatile uint64_t *: __rte_bit_atomic_v_assign64) \
35335326b61SMattias Rönnblom 			(addr, nr, value, memory_order)
35435326b61SMattias Rönnblom 
35535326b61SMattias Rönnblom /**
35635326b61SMattias Rönnblom  * @warning
35735326b61SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
35835326b61SMattias Rönnblom  *
35935326b61SMattias Rönnblom  * Atomically flip bit in word.
36035326b61SMattias Rönnblom  *
36135326b61SMattias Rönnblom  * Generic selection macro to atomically negate the value of the bit
36235326b61SMattias Rönnblom  * specified by @c nr in the word pointed to by @c addr to the value
36335326b61SMattias Rönnblom  * indicated by @c value, with the memory ordering as specified with
36435326b61SMattias Rönnblom  * @c memory_order.
36535326b61SMattias Rönnblom  *
36635326b61SMattias Rönnblom  * @param addr
36735326b61SMattias Rönnblom  *   A pointer to the word to modify.
36835326b61SMattias Rönnblom  * @param nr
36935326b61SMattias Rönnblom  *   The index of the bit.
37035326b61SMattias Rönnblom  * @param memory_order
37135326b61SMattias Rönnblom  *   The memory order to use.
37235326b61SMattias Rönnblom  */
37335326b61SMattias Rönnblom #define rte_bit_atomic_flip(addr, nr, memory_order) \
37435326b61SMattias Rönnblom 	_Generic((addr), \
37535326b61SMattias Rönnblom 		uint32_t *: __rte_bit_atomic_flip32, \
3760883d736SMattias Rönnblom 		volatile uint32_t *: __rte_bit_atomic_v_flip32, \
3770883d736SMattias Rönnblom 		uint64_t *: __rte_bit_atomic_flip64, \
3780883d736SMattias Rönnblom 		volatile uint64_t *: __rte_bit_atomic_v_flip64) \
37935326b61SMattias Rönnblom 			(addr, nr, memory_order)
38035326b61SMattias Rönnblom 
38135326b61SMattias Rönnblom /**
38235326b61SMattias Rönnblom  * @warning
38335326b61SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
38435326b61SMattias Rönnblom  *
38535326b61SMattias Rönnblom  * Atomically test and set a bit in word.
38635326b61SMattias Rönnblom  *
38735326b61SMattias Rönnblom  * Generic selection macro to atomically test and set bit specified by
38835326b61SMattias Rönnblom  * @c nr in the word pointed to by @c addr to '1', with the memory
38935326b61SMattias Rönnblom  * ordering as specified with @c memory_order.
39035326b61SMattias Rönnblom  *
39135326b61SMattias Rönnblom  * @param addr
39235326b61SMattias Rönnblom  *   A pointer to the word to modify.
39335326b61SMattias Rönnblom  * @param nr
39435326b61SMattias Rönnblom  *   The index of the bit.
39535326b61SMattias Rönnblom  * @param memory_order
39635326b61SMattias Rönnblom  *   The memory order to use.
39735326b61SMattias Rönnblom  * @return
39835326b61SMattias Rönnblom  *   Returns true if the bit was set, and false otherwise.
39935326b61SMattias Rönnblom  */
40035326b61SMattias Rönnblom #define rte_bit_atomic_test_and_set(addr, nr, memory_order) \
40135326b61SMattias Rönnblom 	_Generic((addr), \
40235326b61SMattias Rönnblom 		uint32_t *: __rte_bit_atomic_test_and_set32, \
4030883d736SMattias Rönnblom 		volatile uint32_t *: __rte_bit_atomic_v_test_and_set32, \
4040883d736SMattias Rönnblom 		uint64_t *: __rte_bit_atomic_test_and_set64, \
4050883d736SMattias Rönnblom 		volatile uint64_t *: __rte_bit_atomic_v_test_and_set64) \
40635326b61SMattias Rönnblom 			(addr, nr, memory_order)
40735326b61SMattias Rönnblom 
40835326b61SMattias Rönnblom /**
40935326b61SMattias Rönnblom  * @warning
41035326b61SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
41135326b61SMattias Rönnblom  *
41235326b61SMattias Rönnblom  * Atomically test and clear a bit in word.
41335326b61SMattias Rönnblom  *
41435326b61SMattias Rönnblom  * Generic selection macro to atomically test and clear bit specified
41535326b61SMattias Rönnblom  * by @c nr in the word pointed to by @c addr to '0', with the memory
41635326b61SMattias Rönnblom  * ordering as specified with @c memory_order.
41735326b61SMattias Rönnblom  *
41835326b61SMattias Rönnblom  * @param addr
41935326b61SMattias Rönnblom  *   A pointer to the word to modify.
42035326b61SMattias Rönnblom  * @param nr
42135326b61SMattias Rönnblom  *   The index of the bit.
42235326b61SMattias Rönnblom  * @param memory_order
42335326b61SMattias Rönnblom  *   The memory order to use.
42435326b61SMattias Rönnblom  * @return
42535326b61SMattias Rönnblom  *   Returns true if the bit was set, and false otherwise.
42635326b61SMattias Rönnblom  */
42735326b61SMattias Rönnblom #define rte_bit_atomic_test_and_clear(addr, nr, memory_order) \
42835326b61SMattias Rönnblom 	_Generic((addr), \
42935326b61SMattias Rönnblom 		uint32_t *: __rte_bit_atomic_test_and_clear32, \
4300883d736SMattias Rönnblom 		volatile uint32_t *: __rte_bit_atomic_v_test_and_clear32, \
4310883d736SMattias Rönnblom 		uint64_t *: __rte_bit_atomic_test_and_clear64, \
4320883d736SMattias Rönnblom 		volatile uint64_t *: __rte_bit_atomic_v_test_and_clear64) \
43335326b61SMattias Rönnblom 			(addr, nr, memory_order)
43435326b61SMattias Rönnblom 
43535326b61SMattias Rönnblom /**
43635326b61SMattias Rönnblom  * @warning
43735326b61SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
43835326b61SMattias Rönnblom  *
43935326b61SMattias Rönnblom  * Atomically test and assign a bit in word.
44035326b61SMattias Rönnblom  *
44135326b61SMattias Rönnblom  * Generic selection macro to atomically test and assign bit specified
44235326b61SMattias Rönnblom  * by @c nr in the word pointed to by @c addr the value specified by
44335326b61SMattias Rönnblom  * @c value, with the memory ordering as specified with @c
44435326b61SMattias Rönnblom  * memory_order.
44535326b61SMattias Rönnblom  *
44635326b61SMattias Rönnblom  * @param addr
44735326b61SMattias Rönnblom  *   A pointer to the word to modify.
44835326b61SMattias Rönnblom  * @param nr
44935326b61SMattias Rönnblom  *   The index of the bit.
45035326b61SMattias Rönnblom  * @param value
45135326b61SMattias Rönnblom  *   The new value of the bit - true for '1', or false for '0'.
45235326b61SMattias Rönnblom  * @param memory_order
45335326b61SMattias Rönnblom  *   The memory order to use.
45435326b61SMattias Rönnblom  * @return
45535326b61SMattias Rönnblom  *   Returns true if the bit was set, and false otherwise.
45635326b61SMattias Rönnblom  */
45735326b61SMattias Rönnblom #define rte_bit_atomic_test_and_assign(addr, nr, value, memory_order) \
45835326b61SMattias Rönnblom 	_Generic((addr), \
45935326b61SMattias Rönnblom 		uint32_t *: __rte_bit_atomic_test_and_assign32, \
4600883d736SMattias Rönnblom 		volatile uint32_t *: __rte_bit_atomic_v_test_and_assign32, \
4610883d736SMattias Rönnblom 		uint64_t *: __rte_bit_atomic_test_and_assign64, \
4620883d736SMattias Rönnblom 		volatile uint64_t *: __rte_bit_atomic_v_test_and_assign64) \
46335326b61SMattias Rönnblom 			(addr, nr, value, memory_order)
46435326b61SMattias Rönnblom 
465471de107SMattias Rönnblom #define __RTE_GEN_BIT_TEST(variant, qualifier, size) \
466471de107SMattias Rönnblom __rte_experimental \
467471de107SMattias Rönnblom static inline bool \
468471de107SMattias Rönnblom __rte_bit_ ## variant ## test ## size(const qualifier uint ## size ## _t *addr, unsigned int nr) \
469471de107SMattias Rönnblom { \
470471de107SMattias Rönnblom 	RTE_ASSERT(nr < size); \
471471de107SMattias Rönnblom 	uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \
472471de107SMattias Rönnblom 	return *addr & mask; \
473471de107SMattias Rönnblom }
474471de107SMattias Rönnblom 
475471de107SMattias Rönnblom #define __RTE_GEN_BIT_SET(variant, qualifier, size) \
476471de107SMattias Rönnblom __rte_experimental \
477471de107SMattias Rönnblom static inline void \
478471de107SMattias Rönnblom __rte_bit_ ## variant ## set ## size(qualifier uint ## size ## _t *addr, unsigned int nr) \
479471de107SMattias Rönnblom { \
480471de107SMattias Rönnblom 	RTE_ASSERT(nr < size); \
481471de107SMattias Rönnblom 	uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \
482471de107SMattias Rönnblom 	*addr |= mask; \
483471de107SMattias Rönnblom }
484471de107SMattias Rönnblom 
485471de107SMattias Rönnblom #define __RTE_GEN_BIT_CLEAR(variant, qualifier, size) \
486471de107SMattias Rönnblom __rte_experimental \
487471de107SMattias Rönnblom static inline void \
488471de107SMattias Rönnblom __rte_bit_ ## variant ## clear ## size(qualifier uint ## size ## _t *addr, unsigned int nr) \
489471de107SMattias Rönnblom { \
490471de107SMattias Rönnblom 	RTE_ASSERT(nr < size); \
491471de107SMattias Rönnblom 	uint ## size ## _t mask = ~((uint ## size ## _t)1 << nr); \
492471de107SMattias Rönnblom 	(*addr) &= mask; \
493471de107SMattias Rönnblom }
494471de107SMattias Rönnblom 
495471de107SMattias Rönnblom #define __RTE_GEN_BIT_ASSIGN(variant, qualifier, size) \
496471de107SMattias Rönnblom __rte_experimental \
497471de107SMattias Rönnblom static inline void \
498471de107SMattias Rönnblom __rte_bit_ ## variant ## assign ## size(qualifier uint ## size ## _t *addr, unsigned int nr, \
499471de107SMattias Rönnblom 		bool value) \
500471de107SMattias Rönnblom { \
501471de107SMattias Rönnblom 	if (value) \
502471de107SMattias Rönnblom 		__rte_bit_ ## variant ## set ## size(addr, nr); \
503471de107SMattias Rönnblom 	else \
504471de107SMattias Rönnblom 		__rte_bit_ ## variant ## clear ## size(addr, nr); \
505471de107SMattias Rönnblom }
506471de107SMattias Rönnblom 
507471de107SMattias Rönnblom #define __RTE_GEN_BIT_FLIP(variant, qualifier, size) \
508471de107SMattias Rönnblom __rte_experimental \
509471de107SMattias Rönnblom static inline void \
510471de107SMattias Rönnblom __rte_bit_ ## variant ## flip ## size(qualifier uint ## size ## _t *addr, unsigned int nr) \
511471de107SMattias Rönnblom { \
512471de107SMattias Rönnblom 	bool value; \
513471de107SMattias Rönnblom 	value = __rte_bit_ ## variant ## test ## size(addr, nr); \
514471de107SMattias Rönnblom 	__rte_bit_ ## variant ## assign ## size(addr, nr, !value); \
515471de107SMattias Rönnblom }
516471de107SMattias Rönnblom 
517471de107SMattias Rönnblom #define __RTE_GEN_BIT_OPS(v, qualifier, size) \
518471de107SMattias Rönnblom 	__RTE_GEN_BIT_TEST(v, qualifier, size) \
519471de107SMattias Rönnblom 	__RTE_GEN_BIT_SET(v, qualifier, size) \
520471de107SMattias Rönnblom 	__RTE_GEN_BIT_CLEAR(v, qualifier, size) \
521471de107SMattias Rönnblom 	__RTE_GEN_BIT_ASSIGN(v, qualifier, size) \
522471de107SMattias Rönnblom 	__RTE_GEN_BIT_FLIP(v, qualifier, size)
523471de107SMattias Rönnblom 
524471de107SMattias Rönnblom #define __RTE_GEN_BIT_OPS_SIZE(size) \
5250883d736SMattias Rönnblom 	__RTE_GEN_BIT_OPS(,, size) \
5260883d736SMattias Rönnblom 	__RTE_GEN_BIT_OPS(v_, volatile, size)
527471de107SMattias Rönnblom 
5288b65ddc0SDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API
529471de107SMattias Rönnblom __RTE_GEN_BIT_OPS_SIZE(32)
530471de107SMattias Rönnblom __RTE_GEN_BIT_OPS_SIZE(64)
5318b65ddc0SDavid Marchand #endif
532471de107SMattias Rönnblom 
53335326b61SMattias Rönnblom #define __RTE_GEN_BIT_ATOMIC_TEST(variant, qualifier, size) \
53435326b61SMattias Rönnblom __rte_experimental \
53535326b61SMattias Rönnblom static inline bool \
53635326b61SMattias Rönnblom __rte_bit_atomic_ ## variant ## test ## size(const qualifier uint ## size ## _t *addr, \
53735326b61SMattias Rönnblom 		unsigned int nr, int memory_order) \
53835326b61SMattias Rönnblom { \
53935326b61SMattias Rönnblom 	RTE_ASSERT(nr < size); \
54035326b61SMattias Rönnblom 	const qualifier RTE_ATOMIC(uint ## size ## _t) *a_addr = \
54135326b61SMattias Rönnblom 		(const qualifier RTE_ATOMIC(uint ## size ## _t) *)addr; \
54235326b61SMattias Rönnblom 	uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \
54335326b61SMattias Rönnblom 	return rte_atomic_load_explicit(a_addr, memory_order) & mask; \
54435326b61SMattias Rönnblom }
54535326b61SMattias Rönnblom 
54635326b61SMattias Rönnblom #define __RTE_GEN_BIT_ATOMIC_SET(variant, qualifier, size) \
54735326b61SMattias Rönnblom __rte_experimental \
54835326b61SMattias Rönnblom static inline void \
54935326b61SMattias Rönnblom __rte_bit_atomic_ ## variant ## set ## size(qualifier uint ## size ## _t *addr, \
55035326b61SMattias Rönnblom 		unsigned int nr, int memory_order) \
55135326b61SMattias Rönnblom { \
55235326b61SMattias Rönnblom 	RTE_ASSERT(nr < size); \
55335326b61SMattias Rönnblom 	qualifier RTE_ATOMIC(uint ## size ## _t) *a_addr = \
55435326b61SMattias Rönnblom 		(qualifier RTE_ATOMIC(uint ## size ## _t) *)addr; \
55535326b61SMattias Rönnblom 	uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \
55635326b61SMattias Rönnblom 	rte_atomic_fetch_or_explicit(a_addr, mask, memory_order); \
55735326b61SMattias Rönnblom }
55835326b61SMattias Rönnblom 
55935326b61SMattias Rönnblom #define __RTE_GEN_BIT_ATOMIC_CLEAR(variant, qualifier, size) \
56035326b61SMattias Rönnblom __rte_experimental \
56135326b61SMattias Rönnblom static inline void \
56235326b61SMattias Rönnblom __rte_bit_atomic_ ## variant ## clear ## size(qualifier uint ## size ## _t *addr, \
56335326b61SMattias Rönnblom 		unsigned int nr, int memory_order) \
56435326b61SMattias Rönnblom { \
56535326b61SMattias Rönnblom 	RTE_ASSERT(nr < size); \
56635326b61SMattias Rönnblom 	qualifier RTE_ATOMIC(uint ## size ## _t) *a_addr = \
56735326b61SMattias Rönnblom 		(qualifier RTE_ATOMIC(uint ## size ## _t) *)addr; \
56835326b61SMattias Rönnblom 	uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \
56935326b61SMattias Rönnblom 	rte_atomic_fetch_and_explicit(a_addr, ~mask, memory_order); \
57035326b61SMattias Rönnblom }
57135326b61SMattias Rönnblom 
57235326b61SMattias Rönnblom #define __RTE_GEN_BIT_ATOMIC_FLIP(variant, qualifier, size) \
57335326b61SMattias Rönnblom __rte_experimental \
57435326b61SMattias Rönnblom static inline void \
57535326b61SMattias Rönnblom __rte_bit_atomic_ ## variant ## flip ## size(qualifier uint ## size ## _t *addr, \
57635326b61SMattias Rönnblom 		unsigned int nr, int memory_order) \
57735326b61SMattias Rönnblom { \
57835326b61SMattias Rönnblom 	RTE_ASSERT(nr < size); \
57935326b61SMattias Rönnblom 	qualifier RTE_ATOMIC(uint ## size ## _t) *a_addr = \
58035326b61SMattias Rönnblom 		(qualifier RTE_ATOMIC(uint ## size ## _t) *)addr; \
58135326b61SMattias Rönnblom 	uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \
58235326b61SMattias Rönnblom 	rte_atomic_fetch_xor_explicit(a_addr, mask, memory_order); \
58335326b61SMattias Rönnblom }
58435326b61SMattias Rönnblom 
58535326b61SMattias Rönnblom #define __RTE_GEN_BIT_ATOMIC_ASSIGN(variant, qualifier, size) \
58635326b61SMattias Rönnblom __rte_experimental \
58735326b61SMattias Rönnblom static inline void \
58835326b61SMattias Rönnblom __rte_bit_atomic_## variant ## assign ## size(qualifier uint ## size ## _t *addr, \
58935326b61SMattias Rönnblom 		unsigned int nr, bool value, int memory_order) \
59035326b61SMattias Rönnblom { \
59135326b61SMattias Rönnblom 	if (value) \
59235326b61SMattias Rönnblom 		__rte_bit_atomic_ ## variant ## set ## size(addr, nr, memory_order); \
59335326b61SMattias Rönnblom 	else \
59435326b61SMattias Rönnblom 		__rte_bit_atomic_ ## variant ## clear ## size(addr, nr, memory_order); \
59535326b61SMattias Rönnblom }
59635326b61SMattias Rönnblom 
59735326b61SMattias Rönnblom #define __RTE_GEN_BIT_ATOMIC_TEST_AND_SET(variant, qualifier, size) \
59835326b61SMattias Rönnblom __rte_experimental \
59935326b61SMattias Rönnblom static inline bool \
60035326b61SMattias Rönnblom __rte_bit_atomic_ ## variant ## test_and_set ## size(qualifier uint ## size ## _t *addr, \
60135326b61SMattias Rönnblom 		unsigned int nr, int memory_order) \
60235326b61SMattias Rönnblom { \
60335326b61SMattias Rönnblom 	RTE_ASSERT(nr < size); \
60435326b61SMattias Rönnblom 	qualifier RTE_ATOMIC(uint ## size ## _t) *a_addr = \
60535326b61SMattias Rönnblom 		(qualifier RTE_ATOMIC(uint ## size ## _t) *)addr; \
60635326b61SMattias Rönnblom 	uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \
60735326b61SMattias Rönnblom 	uint ## size ## _t prev; \
60835326b61SMattias Rönnblom 	prev = rte_atomic_fetch_or_explicit(a_addr, mask, memory_order); \
60935326b61SMattias Rönnblom 	return prev & mask; \
61035326b61SMattias Rönnblom }
61135326b61SMattias Rönnblom 
61235326b61SMattias Rönnblom #define __RTE_GEN_BIT_ATOMIC_TEST_AND_CLEAR(variant, qualifier, size) \
61335326b61SMattias Rönnblom __rte_experimental \
61435326b61SMattias Rönnblom static inline bool \
61535326b61SMattias Rönnblom __rte_bit_atomic_ ## variant ## test_and_clear ## size(qualifier uint ## size ## _t *addr, \
61635326b61SMattias Rönnblom 		unsigned int nr, int memory_order) \
61735326b61SMattias Rönnblom { \
61835326b61SMattias Rönnblom 	RTE_ASSERT(nr < size); \
61935326b61SMattias Rönnblom 	qualifier RTE_ATOMIC(uint ## size ## _t) *a_addr = \
62035326b61SMattias Rönnblom 		(qualifier RTE_ATOMIC(uint ## size ## _t) *)addr; \
62135326b61SMattias Rönnblom 	uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \
62235326b61SMattias Rönnblom 	uint ## size ## _t prev; \
62335326b61SMattias Rönnblom 	prev = rte_atomic_fetch_and_explicit(a_addr, ~mask, memory_order); \
62435326b61SMattias Rönnblom 	return prev & mask; \
62535326b61SMattias Rönnblom }
62635326b61SMattias Rönnblom 
62735326b61SMattias Rönnblom #define __RTE_GEN_BIT_ATOMIC_TEST_AND_ASSIGN(variant, qualifier, size) \
62835326b61SMattias Rönnblom __rte_experimental \
62935326b61SMattias Rönnblom static inline bool \
63035326b61SMattias Rönnblom __rte_bit_atomic_ ## variant ## test_and_assign ## size( \
63135326b61SMattias Rönnblom 		qualifier uint ## size ## _t *addr, unsigned int nr, bool value, \
63235326b61SMattias Rönnblom 		int memory_order) \
63335326b61SMattias Rönnblom { \
63435326b61SMattias Rönnblom 	if (value) \
63535326b61SMattias Rönnblom 		return __rte_bit_atomic_ ## variant ## test_and_set ## size(addr, nr, \
63635326b61SMattias Rönnblom 			memory_order); \
63735326b61SMattias Rönnblom 	else \
63835326b61SMattias Rönnblom 		return __rte_bit_atomic_ ## variant ## test_and_clear ## size(addr, nr, \
63935326b61SMattias Rönnblom 			memory_order); \
64035326b61SMattias Rönnblom }
64135326b61SMattias Rönnblom 
64235326b61SMattias Rönnblom #define __RTE_GEN_BIT_ATOMIC_OPS(variant, qualifier, size) \
64335326b61SMattias Rönnblom 	__RTE_GEN_BIT_ATOMIC_TEST(variant, qualifier, size) \
64435326b61SMattias Rönnblom 	__RTE_GEN_BIT_ATOMIC_SET(variant, qualifier, size) \
64535326b61SMattias Rönnblom 	__RTE_GEN_BIT_ATOMIC_CLEAR(variant, qualifier, size) \
64635326b61SMattias Rönnblom 	__RTE_GEN_BIT_ATOMIC_ASSIGN(variant, qualifier, size) \
64735326b61SMattias Rönnblom 	__RTE_GEN_BIT_ATOMIC_TEST_AND_SET(variant, qualifier, size) \
64835326b61SMattias Rönnblom 	__RTE_GEN_BIT_ATOMIC_TEST_AND_CLEAR(variant, qualifier, size) \
64935326b61SMattias Rönnblom 	__RTE_GEN_BIT_ATOMIC_TEST_AND_ASSIGN(variant, qualifier, size) \
65035326b61SMattias Rönnblom 	__RTE_GEN_BIT_ATOMIC_FLIP(variant, qualifier, size)
65135326b61SMattias Rönnblom 
65235326b61SMattias Rönnblom #define __RTE_GEN_BIT_ATOMIC_OPS_SIZE(size) \
6530883d736SMattias Rönnblom 	__RTE_GEN_BIT_ATOMIC_OPS(,, size) \
6540883d736SMattias Rönnblom 	__RTE_GEN_BIT_ATOMIC_OPS(v_, volatile, size)
65535326b61SMattias Rönnblom 
6568b65ddc0SDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API
65735326b61SMattias Rönnblom __RTE_GEN_BIT_ATOMIC_OPS_SIZE(32)
65835326b61SMattias Rönnblom __RTE_GEN_BIT_ATOMIC_OPS_SIZE(64)
6598b65ddc0SDavid Marchand #endif
66035326b61SMattias Rönnblom 
66199a2dd95SBruce Richardson /*------------------------ 32-bit relaxed operations ------------------------*/
66299a2dd95SBruce Richardson 
66399a2dd95SBruce Richardson /**
66499a2dd95SBruce Richardson  * Get the target bit from a 32-bit value without memory ordering.
66599a2dd95SBruce Richardson  *
66699a2dd95SBruce Richardson  * @param nr
66799a2dd95SBruce Richardson  *   The target bit to get.
66899a2dd95SBruce Richardson  * @param addr
66999a2dd95SBruce Richardson  *   The address holding the bit.
67099a2dd95SBruce Richardson  * @return
67199a2dd95SBruce Richardson  *   The target bit.
67299a2dd95SBruce Richardson  */
67399a2dd95SBruce Richardson static inline uint32_t
67499a2dd95SBruce Richardson rte_bit_relaxed_get32(unsigned int nr, volatile uint32_t *addr)
67599a2dd95SBruce Richardson {
67699a2dd95SBruce Richardson 	RTE_ASSERT(nr < 32);
67799a2dd95SBruce Richardson 
67899a2dd95SBruce Richardson 	uint32_t mask = UINT32_C(1) << nr;
67999a2dd95SBruce Richardson 	return (*addr) & mask;
68099a2dd95SBruce Richardson }
68199a2dd95SBruce Richardson 
68299a2dd95SBruce Richardson /**
68399a2dd95SBruce Richardson  * Set the target bit in a 32-bit value to 1 without memory ordering.
68499a2dd95SBruce Richardson  *
68599a2dd95SBruce Richardson  * @param nr
68699a2dd95SBruce Richardson  *   The target bit to set.
68799a2dd95SBruce Richardson  * @param addr
68899a2dd95SBruce Richardson  *   The address holding the bit.
68999a2dd95SBruce Richardson  */
69099a2dd95SBruce Richardson static inline void
69199a2dd95SBruce Richardson rte_bit_relaxed_set32(unsigned int nr, volatile uint32_t *addr)
69299a2dd95SBruce Richardson {
69399a2dd95SBruce Richardson 	RTE_ASSERT(nr < 32);
69499a2dd95SBruce Richardson 
69599a2dd95SBruce Richardson 	uint32_t mask = RTE_BIT32(nr);
69699a2dd95SBruce Richardson 	*addr = (*addr) | mask;
69799a2dd95SBruce Richardson }
69899a2dd95SBruce Richardson 
69999a2dd95SBruce Richardson /**
70099a2dd95SBruce Richardson  * Clear the target bit in a 32-bit value to 0 without memory ordering.
70199a2dd95SBruce Richardson  *
70299a2dd95SBruce Richardson  * @param nr
70399a2dd95SBruce Richardson  *   The target bit to clear.
70499a2dd95SBruce Richardson  * @param addr
70599a2dd95SBruce Richardson  *   The address holding the bit.
70699a2dd95SBruce Richardson  */
70799a2dd95SBruce Richardson static inline void
70899a2dd95SBruce Richardson rte_bit_relaxed_clear32(unsigned int nr, volatile uint32_t *addr)
70999a2dd95SBruce Richardson {
71099a2dd95SBruce Richardson 	RTE_ASSERT(nr < 32);
71199a2dd95SBruce Richardson 
71299a2dd95SBruce Richardson 	uint32_t mask = RTE_BIT32(nr);
71399a2dd95SBruce Richardson 	*addr = (*addr) & (~mask);
71499a2dd95SBruce Richardson }
71599a2dd95SBruce Richardson 
71699a2dd95SBruce Richardson /**
71799a2dd95SBruce Richardson  * Return the original bit from a 32-bit value, then set it to 1 without
71899a2dd95SBruce Richardson  * memory ordering.
71999a2dd95SBruce Richardson  *
72099a2dd95SBruce Richardson  * @param nr
72199a2dd95SBruce Richardson  *   The target bit to get and set.
72299a2dd95SBruce Richardson  * @param addr
72399a2dd95SBruce Richardson  *   The address holding the bit.
72499a2dd95SBruce Richardson  * @return
72599a2dd95SBruce Richardson  *   The original bit.
72699a2dd95SBruce Richardson  */
72799a2dd95SBruce Richardson static inline uint32_t
72899a2dd95SBruce Richardson rte_bit_relaxed_test_and_set32(unsigned int nr, volatile uint32_t *addr)
72999a2dd95SBruce Richardson {
73099a2dd95SBruce Richardson 	RTE_ASSERT(nr < 32);
73199a2dd95SBruce Richardson 
73299a2dd95SBruce Richardson 	uint32_t mask = RTE_BIT32(nr);
73399a2dd95SBruce Richardson 	uint32_t val = *addr;
73499a2dd95SBruce Richardson 	*addr = val | mask;
73599a2dd95SBruce Richardson 	return val & mask;
73699a2dd95SBruce Richardson }
73799a2dd95SBruce Richardson 
73899a2dd95SBruce Richardson /**
73999a2dd95SBruce Richardson  * Return the original bit from a 32-bit value, then clear it to 0 without
74099a2dd95SBruce Richardson  * memory ordering.
74199a2dd95SBruce Richardson  *
74299a2dd95SBruce Richardson  * @param nr
74399a2dd95SBruce Richardson  *   The target bit to get and clear.
74499a2dd95SBruce Richardson  * @param addr
74599a2dd95SBruce Richardson  *   The address holding the bit.
74699a2dd95SBruce Richardson  * @return
74799a2dd95SBruce Richardson  *   The original bit.
74899a2dd95SBruce Richardson  */
74999a2dd95SBruce Richardson static inline uint32_t
75099a2dd95SBruce Richardson rte_bit_relaxed_test_and_clear32(unsigned int nr, volatile uint32_t *addr)
75199a2dd95SBruce Richardson {
75299a2dd95SBruce Richardson 	RTE_ASSERT(nr < 32);
75399a2dd95SBruce Richardson 
75499a2dd95SBruce Richardson 	uint32_t mask = RTE_BIT32(nr);
75599a2dd95SBruce Richardson 	uint32_t val = *addr;
75699a2dd95SBruce Richardson 	*addr = val & (~mask);
75799a2dd95SBruce Richardson 	return val & mask;
75899a2dd95SBruce Richardson }
75999a2dd95SBruce Richardson 
76099a2dd95SBruce Richardson /*------------------------ 64-bit relaxed operations ------------------------*/
76199a2dd95SBruce Richardson 
76299a2dd95SBruce Richardson /**
76399a2dd95SBruce Richardson  * Get the target bit from a 64-bit value without memory ordering.
76499a2dd95SBruce Richardson  *
76599a2dd95SBruce Richardson  * @param nr
76699a2dd95SBruce Richardson  *   The target bit to get.
76799a2dd95SBruce Richardson  * @param addr
76899a2dd95SBruce Richardson  *   The address holding the bit.
76999a2dd95SBruce Richardson  * @return
77099a2dd95SBruce Richardson  *   The target bit.
77199a2dd95SBruce Richardson  */
77299a2dd95SBruce Richardson static inline uint64_t
77399a2dd95SBruce Richardson rte_bit_relaxed_get64(unsigned int nr, volatile uint64_t *addr)
77499a2dd95SBruce Richardson {
77599a2dd95SBruce Richardson 	RTE_ASSERT(nr < 64);
77699a2dd95SBruce Richardson 
77799a2dd95SBruce Richardson 	uint64_t mask = RTE_BIT64(nr);
77899a2dd95SBruce Richardson 	return (*addr) & mask;
77999a2dd95SBruce Richardson }
78099a2dd95SBruce Richardson 
78199a2dd95SBruce Richardson /**
78299a2dd95SBruce Richardson  * Set the target bit in a 64-bit value to 1 without memory ordering.
78399a2dd95SBruce Richardson  *
78499a2dd95SBruce Richardson  * @param nr
78599a2dd95SBruce Richardson  *   The target bit to set.
78699a2dd95SBruce Richardson  * @param addr
78799a2dd95SBruce Richardson  *   The address holding the bit.
78899a2dd95SBruce Richardson  */
78999a2dd95SBruce Richardson static inline void
79099a2dd95SBruce Richardson rte_bit_relaxed_set64(unsigned int nr, volatile uint64_t *addr)
79199a2dd95SBruce Richardson {
79299a2dd95SBruce Richardson 	RTE_ASSERT(nr < 64);
79399a2dd95SBruce Richardson 
79499a2dd95SBruce Richardson 	uint64_t mask = RTE_BIT64(nr);
79599a2dd95SBruce Richardson 	(*addr) = (*addr) | mask;
79699a2dd95SBruce Richardson }
79799a2dd95SBruce Richardson 
79899a2dd95SBruce Richardson /**
79999a2dd95SBruce Richardson  * Clear the target bit in a 64-bit value to 0 without memory ordering.
80099a2dd95SBruce Richardson  *
80199a2dd95SBruce Richardson  * @param nr
80299a2dd95SBruce Richardson  *   The target bit to clear.
80399a2dd95SBruce Richardson  * @param addr
80499a2dd95SBruce Richardson  *   The address holding the bit.
80599a2dd95SBruce Richardson  */
80699a2dd95SBruce Richardson static inline void
80799a2dd95SBruce Richardson rte_bit_relaxed_clear64(unsigned int nr, volatile uint64_t *addr)
80899a2dd95SBruce Richardson {
80999a2dd95SBruce Richardson 	RTE_ASSERT(nr < 64);
81099a2dd95SBruce Richardson 
81199a2dd95SBruce Richardson 	uint64_t mask = RTE_BIT64(nr);
81299a2dd95SBruce Richardson 	*addr = (*addr) & (~mask);
81399a2dd95SBruce Richardson }
81499a2dd95SBruce Richardson 
81599a2dd95SBruce Richardson /**
81699a2dd95SBruce Richardson  * Return the original bit from a 64-bit value, then set it to 1 without
81799a2dd95SBruce Richardson  * memory ordering.
81899a2dd95SBruce Richardson  *
81999a2dd95SBruce Richardson  * @param nr
82099a2dd95SBruce Richardson  *   The target bit to get and set.
82199a2dd95SBruce Richardson  * @param addr
82299a2dd95SBruce Richardson  *   The address holding the bit.
82399a2dd95SBruce Richardson  * @return
82499a2dd95SBruce Richardson  *   The original bit.
82599a2dd95SBruce Richardson  */
82699a2dd95SBruce Richardson static inline uint64_t
82799a2dd95SBruce Richardson rte_bit_relaxed_test_and_set64(unsigned int nr, volatile uint64_t *addr)
82899a2dd95SBruce Richardson {
82999a2dd95SBruce Richardson 	RTE_ASSERT(nr < 64);
83099a2dd95SBruce Richardson 
83199a2dd95SBruce Richardson 	uint64_t mask = RTE_BIT64(nr);
83299a2dd95SBruce Richardson 	uint64_t val = *addr;
83399a2dd95SBruce Richardson 	*addr = val | mask;
83499a2dd95SBruce Richardson 	return val;
83599a2dd95SBruce Richardson }
83699a2dd95SBruce Richardson 
83799a2dd95SBruce Richardson /**
83899a2dd95SBruce Richardson  * Return the original bit from a 64-bit value, then clear it to 0 without
83999a2dd95SBruce Richardson  * memory ordering.
84099a2dd95SBruce Richardson  *
84199a2dd95SBruce Richardson  * @param nr
84299a2dd95SBruce Richardson  *   The target bit to get and clear.
84399a2dd95SBruce Richardson  * @param addr
84499a2dd95SBruce Richardson  *   The address holding the bit.
84599a2dd95SBruce Richardson  * @return
84699a2dd95SBruce Richardson  *   The original bit.
84799a2dd95SBruce Richardson  */
84899a2dd95SBruce Richardson static inline uint64_t
84999a2dd95SBruce Richardson rte_bit_relaxed_test_and_clear64(unsigned int nr, volatile uint64_t *addr)
85099a2dd95SBruce Richardson {
85199a2dd95SBruce Richardson 	RTE_ASSERT(nr < 64);
85299a2dd95SBruce Richardson 
85399a2dd95SBruce Richardson 	uint64_t mask = RTE_BIT64(nr);
85499a2dd95SBruce Richardson 	uint64_t val = *addr;
85599a2dd95SBruce Richardson 	*addr = val & (~mask);
85699a2dd95SBruce Richardson 	return val & mask;
85799a2dd95SBruce Richardson }
85899a2dd95SBruce Richardson 
859916c50ddSTyler Retzlaff #ifdef RTE_TOOLCHAIN_MSVC
860916c50ddSTyler Retzlaff 
861916c50ddSTyler Retzlaff /**
862916c50ddSTyler Retzlaff  * Get the count of leading 0-bits in v.
863916c50ddSTyler Retzlaff  *
864916c50ddSTyler Retzlaff  * @param v
865916c50ddSTyler Retzlaff  *   The value.
866916c50ddSTyler Retzlaff  * @return
867916c50ddSTyler Retzlaff  *   The count of leading zero bits.
868916c50ddSTyler Retzlaff  */
869916c50ddSTyler Retzlaff static inline unsigned int
870916c50ddSTyler Retzlaff rte_clz32(uint32_t v)
871916c50ddSTyler Retzlaff {
872916c50ddSTyler Retzlaff 	unsigned long rv;
873916c50ddSTyler Retzlaff 
874916c50ddSTyler Retzlaff 	(void)_BitScanReverse(&rv, v);
875916c50ddSTyler Retzlaff 
876916c50ddSTyler Retzlaff 	return (unsigned int)(sizeof(v) * CHAR_BIT - 1 - rv);
877916c50ddSTyler Retzlaff }
878916c50ddSTyler Retzlaff 
879916c50ddSTyler Retzlaff /**
880916c50ddSTyler Retzlaff  * Get the count of leading 0-bits in v.
881916c50ddSTyler Retzlaff  *
882916c50ddSTyler Retzlaff  * @param v
883916c50ddSTyler Retzlaff  *   The value.
884916c50ddSTyler Retzlaff  * @return
885916c50ddSTyler Retzlaff  *   The count of leading zero bits.
886916c50ddSTyler Retzlaff  */
887916c50ddSTyler Retzlaff static inline unsigned int
888916c50ddSTyler Retzlaff rte_clz64(uint64_t v)
889916c50ddSTyler Retzlaff {
890916c50ddSTyler Retzlaff 	unsigned long rv;
891916c50ddSTyler Retzlaff 
892916c50ddSTyler Retzlaff 	(void)_BitScanReverse64(&rv, v);
893916c50ddSTyler Retzlaff 
894916c50ddSTyler Retzlaff 	return (unsigned int)(sizeof(v) * CHAR_BIT - 1 - rv);
895916c50ddSTyler Retzlaff }
896916c50ddSTyler Retzlaff 
897916c50ddSTyler Retzlaff /**
898916c50ddSTyler Retzlaff  * Get the count of trailing 0-bits in v.
899916c50ddSTyler Retzlaff  *
900916c50ddSTyler Retzlaff  * @param v
901916c50ddSTyler Retzlaff  *   The value.
902916c50ddSTyler Retzlaff  * @return
903916c50ddSTyler Retzlaff  *   The count of trailing zero bits.
904916c50ddSTyler Retzlaff  */
905916c50ddSTyler Retzlaff static inline unsigned int
906916c50ddSTyler Retzlaff rte_ctz32(uint32_t v)
907916c50ddSTyler Retzlaff {
908916c50ddSTyler Retzlaff 	unsigned long rv;
909916c50ddSTyler Retzlaff 
910916c50ddSTyler Retzlaff 	(void)_BitScanForward(&rv, v);
911916c50ddSTyler Retzlaff 
912916c50ddSTyler Retzlaff 	return (unsigned int)rv;
913916c50ddSTyler Retzlaff }
914916c50ddSTyler Retzlaff 
915916c50ddSTyler Retzlaff /**
916916c50ddSTyler Retzlaff  * Get the count of trailing 0-bits in v.
917916c50ddSTyler Retzlaff  *
918916c50ddSTyler Retzlaff  * @param v
919916c50ddSTyler Retzlaff  *   The value.
920916c50ddSTyler Retzlaff  * @return
921916c50ddSTyler Retzlaff  *   The count of trailing zero bits.
922916c50ddSTyler Retzlaff  */
923916c50ddSTyler Retzlaff static inline unsigned int
924916c50ddSTyler Retzlaff rte_ctz64(uint64_t v)
925916c50ddSTyler Retzlaff {
926916c50ddSTyler Retzlaff 	unsigned long rv;
927916c50ddSTyler Retzlaff 
928916c50ddSTyler Retzlaff 	(void)_BitScanForward64(&rv, v);
929916c50ddSTyler Retzlaff 
930916c50ddSTyler Retzlaff 	return (unsigned int)rv;
931916c50ddSTyler Retzlaff }
932916c50ddSTyler Retzlaff 
933916c50ddSTyler Retzlaff /**
934916c50ddSTyler Retzlaff  * Get the count of 1-bits in v.
935916c50ddSTyler Retzlaff  *
936916c50ddSTyler Retzlaff  * @param v
937916c50ddSTyler Retzlaff  *   The value.
938916c50ddSTyler Retzlaff  * @return
939916c50ddSTyler Retzlaff  *   The count of 1-bits.
940916c50ddSTyler Retzlaff  */
941916c50ddSTyler Retzlaff static inline unsigned int
942916c50ddSTyler Retzlaff rte_popcount32(uint32_t v)
943916c50ddSTyler Retzlaff {
944916c50ddSTyler Retzlaff 	return (unsigned int)__popcnt(v);
945916c50ddSTyler Retzlaff }
946916c50ddSTyler Retzlaff 
947916c50ddSTyler Retzlaff /**
948916c50ddSTyler Retzlaff  * Get the count of 1-bits in v.
949916c50ddSTyler Retzlaff  *
950916c50ddSTyler Retzlaff  * @param v
951916c50ddSTyler Retzlaff  *   The value.
952916c50ddSTyler Retzlaff  * @return
953916c50ddSTyler Retzlaff  *   The count of 1-bits.
954916c50ddSTyler Retzlaff  */
955916c50ddSTyler Retzlaff static inline unsigned int
956916c50ddSTyler Retzlaff rte_popcount64(uint64_t v)
957916c50ddSTyler Retzlaff {
958916c50ddSTyler Retzlaff 	return (unsigned int)__popcnt64(v);
959916c50ddSTyler Retzlaff }
960916c50ddSTyler Retzlaff 
961*21cab84fSTyler Retzlaff /**
962*21cab84fSTyler Retzlaff  * @warning
963*21cab84fSTyler Retzlaff  * @b EXPERIMENTAL: this API may change without prior notice.
964*21cab84fSTyler Retzlaff  *
965*21cab84fSTyler Retzlaff  * Search v from least significant bit (LSB) to the most
966*21cab84fSTyler Retzlaff  * significant bit (MSB) for a set bit (1).
967*21cab84fSTyler Retzlaff  *
968*21cab84fSTyler Retzlaff  * @param v
969*21cab84fSTyler Retzlaff  *   The value.
970*21cab84fSTyler Retzlaff  * @return
971*21cab84fSTyler Retzlaff  *   Bit index + 1 if a set bit is found, zero otherwise.
972*21cab84fSTyler Retzlaff  */
973*21cab84fSTyler Retzlaff __rte_experimental
974*21cab84fSTyler Retzlaff static inline unsigned int
975*21cab84fSTyler Retzlaff rte_ffs32(uint32_t v)
976*21cab84fSTyler Retzlaff {
977*21cab84fSTyler Retzlaff 	unsigned long rv;
978*21cab84fSTyler Retzlaff 
979*21cab84fSTyler Retzlaff 	if (_BitScanForward(&rv, v) == 0)
980*21cab84fSTyler Retzlaff 		return 0;
981*21cab84fSTyler Retzlaff 
982*21cab84fSTyler Retzlaff 	return (unsigned int)rv + 1;
983*21cab84fSTyler Retzlaff }
984*21cab84fSTyler Retzlaff 
985*21cab84fSTyler Retzlaff /**
986*21cab84fSTyler Retzlaff  * @warning
987*21cab84fSTyler Retzlaff  * @b EXPERIMENTAL: this API may change without prior notice.
988*21cab84fSTyler Retzlaff  *
989*21cab84fSTyler Retzlaff  * Search v from least significant bit (LSB) to the most
990*21cab84fSTyler Retzlaff  * significant bit (MSB) for a set bit (1).
991*21cab84fSTyler Retzlaff  *
992*21cab84fSTyler Retzlaff  * @param v
993*21cab84fSTyler Retzlaff  *   The value.
994*21cab84fSTyler Retzlaff  * @return
995*21cab84fSTyler Retzlaff  *   Bit index + 1 if a set bit is found, zero otherwise.
996*21cab84fSTyler Retzlaff  */
997*21cab84fSTyler Retzlaff __rte_experimental
998*21cab84fSTyler Retzlaff static inline unsigned int
999*21cab84fSTyler Retzlaff rte_ffs64(uint64_t v)
1000*21cab84fSTyler Retzlaff {
1001*21cab84fSTyler Retzlaff 	unsigned long rv;
1002*21cab84fSTyler Retzlaff 
1003*21cab84fSTyler Retzlaff 	if (_BitScanForward64(&rv, v) == 0)
1004*21cab84fSTyler Retzlaff 		return 0;
1005*21cab84fSTyler Retzlaff 
1006*21cab84fSTyler Retzlaff 	return (unsigned int)rv + 1;
1007*21cab84fSTyler Retzlaff }
1008*21cab84fSTyler Retzlaff 
1009916c50ddSTyler Retzlaff #else
1010916c50ddSTyler Retzlaff 
1011916c50ddSTyler Retzlaff /**
1012916c50ddSTyler Retzlaff  * Get the count of leading 0-bits in v.
1013916c50ddSTyler Retzlaff  *
1014916c50ddSTyler Retzlaff  * @param v
1015916c50ddSTyler Retzlaff  *   The value.
1016916c50ddSTyler Retzlaff  * @return
1017916c50ddSTyler Retzlaff  *   The count of leading zero bits.
1018916c50ddSTyler Retzlaff  */
1019916c50ddSTyler Retzlaff static inline unsigned int
1020916c50ddSTyler Retzlaff rte_clz32(uint32_t v)
1021916c50ddSTyler Retzlaff {
1022916c50ddSTyler Retzlaff 	return (unsigned int)__builtin_clz(v);
1023916c50ddSTyler Retzlaff }
1024916c50ddSTyler Retzlaff 
1025916c50ddSTyler Retzlaff /**
1026916c50ddSTyler Retzlaff  * Get the count of leading 0-bits in v.
1027916c50ddSTyler Retzlaff  *
1028916c50ddSTyler Retzlaff  * @param v
1029916c50ddSTyler Retzlaff  *   The value.
1030916c50ddSTyler Retzlaff  * @return
1031916c50ddSTyler Retzlaff  *   The count of leading zero bits.
1032916c50ddSTyler Retzlaff  */
1033916c50ddSTyler Retzlaff static inline unsigned int
1034916c50ddSTyler Retzlaff rte_clz64(uint64_t v)
1035916c50ddSTyler Retzlaff {
1036916c50ddSTyler Retzlaff 	return (unsigned int)__builtin_clzll(v);
1037916c50ddSTyler Retzlaff }
1038916c50ddSTyler Retzlaff 
1039916c50ddSTyler Retzlaff /**
1040916c50ddSTyler Retzlaff  * Get the count of trailing 0-bits in v.
1041916c50ddSTyler Retzlaff  *
1042916c50ddSTyler Retzlaff  * @param v
1043916c50ddSTyler Retzlaff  *   The value.
1044916c50ddSTyler Retzlaff  * @return
1045916c50ddSTyler Retzlaff  *   The count of trailing zero bits.
1046916c50ddSTyler Retzlaff  */
1047916c50ddSTyler Retzlaff static inline unsigned int
1048916c50ddSTyler Retzlaff rte_ctz32(uint32_t v)
1049916c50ddSTyler Retzlaff {
1050916c50ddSTyler Retzlaff 	return (unsigned int)__builtin_ctz(v);
1051916c50ddSTyler Retzlaff }
1052916c50ddSTyler Retzlaff 
1053916c50ddSTyler Retzlaff /**
1054916c50ddSTyler Retzlaff  * Get the count of trailing 0-bits in v.
1055916c50ddSTyler Retzlaff  *
1056916c50ddSTyler Retzlaff  * @param v
1057916c50ddSTyler Retzlaff  *   The value.
1058916c50ddSTyler Retzlaff  * @return
1059916c50ddSTyler Retzlaff  *   The count of trailing zero bits.
1060916c50ddSTyler Retzlaff  */
1061916c50ddSTyler Retzlaff static inline unsigned int
1062916c50ddSTyler Retzlaff rte_ctz64(uint64_t v)
1063916c50ddSTyler Retzlaff {
1064916c50ddSTyler Retzlaff 	return (unsigned int)__builtin_ctzll(v);
1065916c50ddSTyler Retzlaff }
1066916c50ddSTyler Retzlaff 
1067916c50ddSTyler Retzlaff /**
1068916c50ddSTyler Retzlaff  * Get the count of 1-bits in v.
1069916c50ddSTyler Retzlaff  *
1070916c50ddSTyler Retzlaff  * @param v
1071916c50ddSTyler Retzlaff  *   The value.
1072916c50ddSTyler Retzlaff  * @return
1073916c50ddSTyler Retzlaff  *   The count of 1-bits.
1074916c50ddSTyler Retzlaff  */
1075916c50ddSTyler Retzlaff static inline unsigned int
1076916c50ddSTyler Retzlaff rte_popcount32(uint32_t v)
1077916c50ddSTyler Retzlaff {
1078916c50ddSTyler Retzlaff 	return (unsigned int)__builtin_popcount(v);
1079916c50ddSTyler Retzlaff }
1080916c50ddSTyler Retzlaff 
1081916c50ddSTyler Retzlaff /**
1082916c50ddSTyler Retzlaff  * Get the count of 1-bits in v.
1083916c50ddSTyler Retzlaff  *
1084916c50ddSTyler Retzlaff  * @param v
1085916c50ddSTyler Retzlaff  *   The value.
1086916c50ddSTyler Retzlaff  * @return
1087916c50ddSTyler Retzlaff  *   The count of 1-bits.
1088916c50ddSTyler Retzlaff  */
1089916c50ddSTyler Retzlaff static inline unsigned int
1090916c50ddSTyler Retzlaff rte_popcount64(uint64_t v)
1091916c50ddSTyler Retzlaff {
1092916c50ddSTyler Retzlaff 	return (unsigned int)__builtin_popcountll(v);
1093916c50ddSTyler Retzlaff }
1094916c50ddSTyler Retzlaff 
1095*21cab84fSTyler Retzlaff /**
1096*21cab84fSTyler Retzlaff  * @warning
1097*21cab84fSTyler Retzlaff  * @b EXPERIMENTAL: this API may change without prior notice.
1098*21cab84fSTyler Retzlaff  *
1099*21cab84fSTyler Retzlaff  * Search v from least significant bit (LSB) to the most
1100*21cab84fSTyler Retzlaff  * significant bit (MSB) for a set bit (1).
1101*21cab84fSTyler Retzlaff  *
1102*21cab84fSTyler Retzlaff  * @param v
1103*21cab84fSTyler Retzlaff  *   The value.
1104*21cab84fSTyler Retzlaff  * @return
1105*21cab84fSTyler Retzlaff  *   Bit index + 1 if a set bit is found, zero otherwise.
1106*21cab84fSTyler Retzlaff  */
1107*21cab84fSTyler Retzlaff __rte_experimental
1108*21cab84fSTyler Retzlaff static inline unsigned int
1109*21cab84fSTyler Retzlaff rte_ffs32(uint32_t v)
1110*21cab84fSTyler Retzlaff {
1111*21cab84fSTyler Retzlaff 	return (unsigned int)__builtin_ffs(v);
1112*21cab84fSTyler Retzlaff }
1113*21cab84fSTyler Retzlaff 
1114*21cab84fSTyler Retzlaff /**
1115*21cab84fSTyler Retzlaff  * @warning
1116*21cab84fSTyler Retzlaff  * @b EXPERIMENTAL: this API may change without prior notice.
1117*21cab84fSTyler Retzlaff  *
1118*21cab84fSTyler Retzlaff  * Search v from least significant bit (LSB) to the most
1119*21cab84fSTyler Retzlaff  * significant bit (MSB) for a set bit (1).
1120*21cab84fSTyler Retzlaff  *
1121*21cab84fSTyler Retzlaff  * @param v
1122*21cab84fSTyler Retzlaff  *   The value.
1123*21cab84fSTyler Retzlaff  * @return
1124*21cab84fSTyler Retzlaff  *   Bit index + 1 if a set bit is found, zero otherwise.
1125*21cab84fSTyler Retzlaff  */
1126*21cab84fSTyler Retzlaff __rte_experimental
1127*21cab84fSTyler Retzlaff static inline unsigned int
1128*21cab84fSTyler Retzlaff rte_ffs64(uint64_t v)
1129*21cab84fSTyler Retzlaff {
1130*21cab84fSTyler Retzlaff 	return (unsigned int)__builtin_ffsll(v);
1131*21cab84fSTyler Retzlaff }
1132*21cab84fSTyler Retzlaff 
1133916c50ddSTyler Retzlaff #endif
1134916c50ddSTyler Retzlaff 
11357253e3d2STyler Retzlaff /**
11367253e3d2STyler Retzlaff  * Combines 32b inputs most significant set bits into the least
11377253e3d2STyler Retzlaff  * significant bits to construct a value with the same MSBs as x
11387253e3d2STyler Retzlaff  * but all 1's under it.
11397253e3d2STyler Retzlaff  *
11407253e3d2STyler Retzlaff  * @param x
11417253e3d2STyler Retzlaff  *    The integer whose MSBs need to be combined with its LSBs
11427253e3d2STyler Retzlaff  * @return
11437253e3d2STyler Retzlaff  *    The combined value.
11447253e3d2STyler Retzlaff  */
11457253e3d2STyler Retzlaff static inline uint32_t
11467253e3d2STyler Retzlaff rte_combine32ms1b(uint32_t x)
11477253e3d2STyler Retzlaff {
11487253e3d2STyler Retzlaff 	x |= x >> 1;
11497253e3d2STyler Retzlaff 	x |= x >> 2;
11507253e3d2STyler Retzlaff 	x |= x >> 4;
11517253e3d2STyler Retzlaff 	x |= x >> 8;
11527253e3d2STyler Retzlaff 	x |= x >> 16;
11537253e3d2STyler Retzlaff 
11547253e3d2STyler Retzlaff 	return x;
11557253e3d2STyler Retzlaff }
11567253e3d2STyler Retzlaff 
11577253e3d2STyler Retzlaff /**
11587253e3d2STyler Retzlaff  * Combines 64b inputs most significant set bits into the least
11597253e3d2STyler Retzlaff  * significant bits to construct a value with the same MSBs as x
11607253e3d2STyler Retzlaff  * but all 1's under it.
11617253e3d2STyler Retzlaff  *
11627253e3d2STyler Retzlaff  * @param v
11637253e3d2STyler Retzlaff  *    The integer whose MSBs need to be combined with its LSBs
11647253e3d2STyler Retzlaff  * @return
11657253e3d2STyler Retzlaff  *    The combined value.
11667253e3d2STyler Retzlaff  */
11677253e3d2STyler Retzlaff static inline uint64_t
11687253e3d2STyler Retzlaff rte_combine64ms1b(uint64_t v)
11697253e3d2STyler Retzlaff {
11707253e3d2STyler Retzlaff 	v |= v >> 1;
11717253e3d2STyler Retzlaff 	v |= v >> 2;
11727253e3d2STyler Retzlaff 	v |= v >> 4;
11737253e3d2STyler Retzlaff 	v |= v >> 8;
11747253e3d2STyler Retzlaff 	v |= v >> 16;
11757253e3d2STyler Retzlaff 	v |= v >> 32;
11767253e3d2STyler Retzlaff 
11777253e3d2STyler Retzlaff 	return v;
11787253e3d2STyler Retzlaff }
11797253e3d2STyler Retzlaff 
11807253e3d2STyler Retzlaff /**
11817253e3d2STyler Retzlaff  * Searches the input parameter for the least significant set bit
11827253e3d2STyler Retzlaff  * (starting from zero).
11837253e3d2STyler Retzlaff  * If a least significant 1 bit is found, its bit index is returned.
11847253e3d2STyler Retzlaff  * If the content of the input parameter is zero, then the content of the return
11857253e3d2STyler Retzlaff  * value is undefined.
11867253e3d2STyler Retzlaff  * @param v
11877253e3d2STyler Retzlaff  *     input parameter, should not be zero.
11887253e3d2STyler Retzlaff  * @return
11897253e3d2STyler Retzlaff  *     least significant set bit in the input parameter.
11907253e3d2STyler Retzlaff  */
11917253e3d2STyler Retzlaff static inline uint32_t
11927253e3d2STyler Retzlaff rte_bsf32(uint32_t v)
11937253e3d2STyler Retzlaff {
119418898c4dSTyler Retzlaff 	return (uint32_t)rte_ctz32(v);
11957253e3d2STyler Retzlaff }
11967253e3d2STyler Retzlaff 
11977253e3d2STyler Retzlaff /**
11987253e3d2STyler Retzlaff  * Searches the input parameter for the least significant set bit
11997253e3d2STyler Retzlaff  * (starting from zero). Safe version (checks for input parameter being zero).
12007253e3d2STyler Retzlaff  *
12017253e3d2STyler Retzlaff  * @warning ``pos`` must be a valid pointer. It is not checked!
12027253e3d2STyler Retzlaff  *
12037253e3d2STyler Retzlaff  * @param v
12047253e3d2STyler Retzlaff  *     The input parameter.
12057253e3d2STyler Retzlaff  * @param pos
12067253e3d2STyler Retzlaff  *     If ``v`` was not 0, this value will contain position of least significant
12077253e3d2STyler Retzlaff  *     bit within the input parameter.
12087253e3d2STyler Retzlaff  * @return
12097253e3d2STyler Retzlaff  *     Returns 0 if ``v`` was 0, otherwise returns 1.
12107253e3d2STyler Retzlaff  */
12117253e3d2STyler Retzlaff static inline int
12127253e3d2STyler Retzlaff rte_bsf32_safe(uint32_t v, uint32_t *pos)
12137253e3d2STyler Retzlaff {
12147253e3d2STyler Retzlaff 	if (v == 0)
12157253e3d2STyler Retzlaff 		return 0;
12167253e3d2STyler Retzlaff 
12177253e3d2STyler Retzlaff 	*pos = rte_bsf32(v);
12187253e3d2STyler Retzlaff 	return 1;
12197253e3d2STyler Retzlaff }
12207253e3d2STyler Retzlaff 
12217253e3d2STyler Retzlaff /**
12227253e3d2STyler Retzlaff  * Searches the input parameter for the least significant set bit
12237253e3d2STyler Retzlaff  * (starting from zero).
12247253e3d2STyler Retzlaff  * If a least significant 1 bit is found, its bit index is returned.
12257253e3d2STyler Retzlaff  * If the content of the input parameter is zero, then the content of the return
12267253e3d2STyler Retzlaff  * value is undefined.
12277253e3d2STyler Retzlaff  * @param v
12287253e3d2STyler Retzlaff  *     input parameter, should not be zero.
12297253e3d2STyler Retzlaff  * @return
12307253e3d2STyler Retzlaff  *     least significant set bit in the input parameter.
12317253e3d2STyler Retzlaff  */
12327253e3d2STyler Retzlaff static inline uint32_t
12337253e3d2STyler Retzlaff rte_bsf64(uint64_t v)
12347253e3d2STyler Retzlaff {
123518898c4dSTyler Retzlaff 	return (uint32_t)rte_ctz64(v);
12367253e3d2STyler Retzlaff }
12377253e3d2STyler Retzlaff 
12387253e3d2STyler Retzlaff /**
12397253e3d2STyler Retzlaff  * Searches the input parameter for the least significant set bit
12407253e3d2STyler Retzlaff  * (starting from zero). Safe version (checks for input parameter being zero).
12417253e3d2STyler Retzlaff  *
12427253e3d2STyler Retzlaff  * @warning ``pos`` must be a valid pointer. It is not checked!
12437253e3d2STyler Retzlaff  *
12447253e3d2STyler Retzlaff  * @param v
12457253e3d2STyler Retzlaff  *     The input parameter.
12467253e3d2STyler Retzlaff  * @param pos
12477253e3d2STyler Retzlaff  *     If ``v`` was not 0, this value will contain position of least significant
12487253e3d2STyler Retzlaff  *     bit within the input parameter.
12497253e3d2STyler Retzlaff  * @return
12507253e3d2STyler Retzlaff  *     Returns 0 if ``v`` was 0, otherwise returns 1.
12517253e3d2STyler Retzlaff  */
12527253e3d2STyler Retzlaff static inline int
12537253e3d2STyler Retzlaff rte_bsf64_safe(uint64_t v, uint32_t *pos)
12547253e3d2STyler Retzlaff {
12557253e3d2STyler Retzlaff 	if (v == 0)
12567253e3d2STyler Retzlaff 		return 0;
12577253e3d2STyler Retzlaff 
12587253e3d2STyler Retzlaff 	*pos = rte_bsf64(v);
12597253e3d2STyler Retzlaff 	return 1;
12607253e3d2STyler Retzlaff }
12617253e3d2STyler Retzlaff 
12627253e3d2STyler Retzlaff /**
12637253e3d2STyler Retzlaff  * Return the last (most-significant) bit set.
12647253e3d2STyler Retzlaff  *
12657253e3d2STyler Retzlaff  * @note The last (most significant) bit is at position 32.
12667253e3d2STyler Retzlaff  * @note rte_fls_u32(0) = 0, rte_fls_u32(1) = 1, rte_fls_u32(0x80000000) = 32
12677253e3d2STyler Retzlaff  *
12687253e3d2STyler Retzlaff  * @param x
12697253e3d2STyler Retzlaff  *     The input parameter.
12707253e3d2STyler Retzlaff  * @return
12717253e3d2STyler Retzlaff  *     The last (most-significant) bit set, or 0 if the input is 0.
12727253e3d2STyler Retzlaff  */
12737253e3d2STyler Retzlaff static inline uint32_t
12747253e3d2STyler Retzlaff rte_fls_u32(uint32_t x)
12757253e3d2STyler Retzlaff {
127618898c4dSTyler Retzlaff 	return (x == 0) ? 0 : 32 - rte_clz32(x);
12777253e3d2STyler Retzlaff }
12787253e3d2STyler Retzlaff 
12797253e3d2STyler Retzlaff /**
12807253e3d2STyler Retzlaff  * Return the last (most-significant) bit set.
12817253e3d2STyler Retzlaff  *
12827253e3d2STyler Retzlaff  * @note The last (most significant) bit is at position 64.
12837253e3d2STyler Retzlaff  * @note rte_fls_u64(0) = 0, rte_fls_u64(1) = 1,
12847253e3d2STyler Retzlaff  *       rte_fls_u64(0x8000000000000000) = 64
12857253e3d2STyler Retzlaff  *
12867253e3d2STyler Retzlaff  * @param x
12877253e3d2STyler Retzlaff  *     The input parameter.
12887253e3d2STyler Retzlaff  * @return
12897253e3d2STyler Retzlaff  *     The last (most-significant) bit set, or 0 if the input is 0.
12907253e3d2STyler Retzlaff  */
12917253e3d2STyler Retzlaff static inline uint32_t
12927253e3d2STyler Retzlaff rte_fls_u64(uint64_t x)
12937253e3d2STyler Retzlaff {
129418898c4dSTyler Retzlaff 	return (x == 0) ? 0 : 64 - rte_clz64(x);
12957253e3d2STyler Retzlaff }
12967253e3d2STyler Retzlaff 
12977253e3d2STyler Retzlaff /*********** Macros to work with powers of 2 ********/
12987253e3d2STyler Retzlaff 
12997253e3d2STyler Retzlaff /**
13007253e3d2STyler Retzlaff  * Macro to return 1 if n is a power of 2, 0 otherwise
13017253e3d2STyler Retzlaff  */
13027253e3d2STyler Retzlaff #define RTE_IS_POWER_OF_2(n) ((n) && !(((n) - 1) & (n)))
13037253e3d2STyler Retzlaff 
13047253e3d2STyler Retzlaff /**
13057253e3d2STyler Retzlaff  * Returns true if n is a power of 2
13067253e3d2STyler Retzlaff  * @param n
13077253e3d2STyler Retzlaff  *     Number to check
13087253e3d2STyler Retzlaff  * @return 1 if true, 0 otherwise
13097253e3d2STyler Retzlaff  */
13107253e3d2STyler Retzlaff static inline int
13117253e3d2STyler Retzlaff rte_is_power_of_2(uint32_t n)
13127253e3d2STyler Retzlaff {
13137253e3d2STyler Retzlaff 	return n && !(n & (n - 1));
13147253e3d2STyler Retzlaff }
13157253e3d2STyler Retzlaff 
13167253e3d2STyler Retzlaff /**
13177253e3d2STyler Retzlaff  * Aligns input parameter to the next power of 2
13187253e3d2STyler Retzlaff  *
13197253e3d2STyler Retzlaff  * @param x
13207253e3d2STyler Retzlaff  *   The integer value to align
13217253e3d2STyler Retzlaff  *
13227253e3d2STyler Retzlaff  * @return
13237253e3d2STyler Retzlaff  *   Input parameter aligned to the next power of 2
13247253e3d2STyler Retzlaff  */
13257253e3d2STyler Retzlaff static inline uint32_t
13267253e3d2STyler Retzlaff rte_align32pow2(uint32_t x)
13277253e3d2STyler Retzlaff {
13287253e3d2STyler Retzlaff 	x--;
13297253e3d2STyler Retzlaff 	x = rte_combine32ms1b(x);
13307253e3d2STyler Retzlaff 
13317253e3d2STyler Retzlaff 	return x + 1;
13327253e3d2STyler Retzlaff }
13337253e3d2STyler Retzlaff 
13347253e3d2STyler Retzlaff /**
13357253e3d2STyler Retzlaff  * Aligns input parameter to the previous power of 2
13367253e3d2STyler Retzlaff  *
13377253e3d2STyler Retzlaff  * @param x
13387253e3d2STyler Retzlaff  *   The integer value to align
13397253e3d2STyler Retzlaff  *
13407253e3d2STyler Retzlaff  * @return
13417253e3d2STyler Retzlaff  *   Input parameter aligned to the previous power of 2
13427253e3d2STyler Retzlaff  */
13437253e3d2STyler Retzlaff static inline uint32_t
13447253e3d2STyler Retzlaff rte_align32prevpow2(uint32_t x)
13457253e3d2STyler Retzlaff {
13467253e3d2STyler Retzlaff 	x = rte_combine32ms1b(x);
13477253e3d2STyler Retzlaff 
13487253e3d2STyler Retzlaff 	return x - (x >> 1);
13497253e3d2STyler Retzlaff }
13507253e3d2STyler Retzlaff 
13517253e3d2STyler Retzlaff /**
13527253e3d2STyler Retzlaff  * Aligns 64b input parameter to the next power of 2
13537253e3d2STyler Retzlaff  *
13547253e3d2STyler Retzlaff  * @param v
13557253e3d2STyler Retzlaff  *   The 64b value to align
13567253e3d2STyler Retzlaff  *
13577253e3d2STyler Retzlaff  * @return
13587253e3d2STyler Retzlaff  *   Input parameter aligned to the next power of 2
13597253e3d2STyler Retzlaff  */
13607253e3d2STyler Retzlaff static inline uint64_t
13617253e3d2STyler Retzlaff rte_align64pow2(uint64_t v)
13627253e3d2STyler Retzlaff {
13637253e3d2STyler Retzlaff 	v--;
13647253e3d2STyler Retzlaff 	v = rte_combine64ms1b(v);
13657253e3d2STyler Retzlaff 
13667253e3d2STyler Retzlaff 	return v + 1;
13677253e3d2STyler Retzlaff }
13687253e3d2STyler Retzlaff 
13697253e3d2STyler Retzlaff /**
13707253e3d2STyler Retzlaff  * Aligns 64b input parameter to the previous power of 2
13717253e3d2STyler Retzlaff  *
13727253e3d2STyler Retzlaff  * @param v
13737253e3d2STyler Retzlaff  *   The 64b value to align
13747253e3d2STyler Retzlaff  *
13757253e3d2STyler Retzlaff  * @return
13767253e3d2STyler Retzlaff  *   Input parameter aligned to the previous power of 2
13777253e3d2STyler Retzlaff  */
13787253e3d2STyler Retzlaff static inline uint64_t
13797253e3d2STyler Retzlaff rte_align64prevpow2(uint64_t v)
13807253e3d2STyler Retzlaff {
13817253e3d2STyler Retzlaff 	v = rte_combine64ms1b(v);
13827253e3d2STyler Retzlaff 
13837253e3d2STyler Retzlaff 	return v - (v >> 1);
13847253e3d2STyler Retzlaff }
13857253e3d2STyler Retzlaff 
13867253e3d2STyler Retzlaff /**
13877253e3d2STyler Retzlaff  * Return the rounded-up log2 of a integer.
13887253e3d2STyler Retzlaff  *
13897253e3d2STyler Retzlaff  * @note Contrary to the logarithm mathematical operation,
13907253e3d2STyler Retzlaff  * rte_log2_u32(0) == 0 and not -inf.
13917253e3d2STyler Retzlaff  *
13927253e3d2STyler Retzlaff  * @param v
13937253e3d2STyler Retzlaff  *     The input parameter.
13947253e3d2STyler Retzlaff  * @return
13957253e3d2STyler Retzlaff  *     The rounded-up log2 of the input, or 0 if the input is 0.
13967253e3d2STyler Retzlaff  */
13977253e3d2STyler Retzlaff static inline uint32_t
13987253e3d2STyler Retzlaff rte_log2_u32(uint32_t v)
13997253e3d2STyler Retzlaff {
14007253e3d2STyler Retzlaff 	if (v == 0)
14017253e3d2STyler Retzlaff 		return 0;
14027253e3d2STyler Retzlaff 	v = rte_align32pow2(v);
14037253e3d2STyler Retzlaff 	return rte_bsf32(v);
14047253e3d2STyler Retzlaff }
14057253e3d2STyler Retzlaff 
14067253e3d2STyler Retzlaff /**
14077253e3d2STyler Retzlaff  * Return the rounded-up log2 of a 64-bit integer.
14087253e3d2STyler Retzlaff  *
14097253e3d2STyler Retzlaff  * @note Contrary to the logarithm mathematical operation,
14107253e3d2STyler Retzlaff  * rte_log2_u64(0) == 0 and not -inf.
14117253e3d2STyler Retzlaff  *
14127253e3d2STyler Retzlaff  * @param v
14137253e3d2STyler Retzlaff  *     The input parameter.
14147253e3d2STyler Retzlaff  * @return
14157253e3d2STyler Retzlaff  *     The rounded-up log2 of the input, or 0 if the input is 0.
14167253e3d2STyler Retzlaff  */
14177253e3d2STyler Retzlaff static inline uint32_t
14187253e3d2STyler Retzlaff rte_log2_u64(uint64_t v)
14197253e3d2STyler Retzlaff {
14207253e3d2STyler Retzlaff 	if (v == 0)
14217253e3d2STyler Retzlaff 		return 0;
14227253e3d2STyler Retzlaff 	v = rte_align64pow2(v);
14237253e3d2STyler Retzlaff 	/* we checked for v being 0 already, so no undefined behavior */
14247253e3d2STyler Retzlaff 	return rte_bsf64(v);
14257253e3d2STyler Retzlaff }
14267253e3d2STyler Retzlaff 
1427d7e9c02cSBrian Dooley #ifdef __cplusplus
1428d7e9c02cSBrian Dooley }
1429471de107SMattias Rönnblom 
1430471de107SMattias Rönnblom /*
1431471de107SMattias Rönnblom  * Since C++ doesn't support generic selection (i.e., _Generic),
1432471de107SMattias Rönnblom  * function overloading is used instead. Such functions must be
1433471de107SMattias Rönnblom  * defined outside 'extern "C"' to be accepted by the compiler.
1434471de107SMattias Rönnblom  */
1435471de107SMattias Rönnblom 
1436471de107SMattias Rönnblom #undef rte_bit_test
1437471de107SMattias Rönnblom #undef rte_bit_set
1438471de107SMattias Rönnblom #undef rte_bit_clear
1439471de107SMattias Rönnblom #undef rte_bit_assign
1440471de107SMattias Rönnblom #undef rte_bit_flip
1441471de107SMattias Rönnblom 
144235326b61SMattias Rönnblom #undef rte_bit_atomic_test
144335326b61SMattias Rönnblom #undef rte_bit_atomic_set
144435326b61SMattias Rönnblom #undef rte_bit_atomic_clear
144535326b61SMattias Rönnblom #undef rte_bit_atomic_assign
144635326b61SMattias Rönnblom #undef rte_bit_atomic_flip
144735326b61SMattias Rönnblom #undef rte_bit_atomic_test_and_set
144835326b61SMattias Rönnblom #undef rte_bit_atomic_test_and_clear
144935326b61SMattias Rönnblom #undef rte_bit_atomic_test_and_assign
145035326b61SMattias Rönnblom 
1451471de107SMattias Rönnblom #define __RTE_BIT_OVERLOAD_V_2(family, v, fun, qualifier, size, arg1_type, arg1_name) \
1452471de107SMattias Rönnblom static inline void \
1453471de107SMattias Rönnblom rte_bit_ ## family ## fun(qualifier uint ## size ## _t *addr, arg1_type arg1_name) \
1454471de107SMattias Rönnblom { \
1455471de107SMattias Rönnblom 	__rte_bit_ ## family ## v ## fun ## size(addr, arg1_name); \
1456471de107SMattias Rönnblom }
1457471de107SMattias Rönnblom 
1458471de107SMattias Rönnblom #define __RTE_BIT_OVERLOAD_SZ_2(family, fun, qualifier, size, arg1_type, arg1_name) \
14590883d736SMattias Rönnblom 	__RTE_BIT_OVERLOAD_V_2(family,, fun, qualifier, size, arg1_type, arg1_name) \
14600883d736SMattias Rönnblom 	__RTE_BIT_OVERLOAD_V_2(family, v_, fun, qualifier volatile, size, arg1_type, arg1_name)
1461471de107SMattias Rönnblom 
1462471de107SMattias Rönnblom #define __RTE_BIT_OVERLOAD_2(family, fun, qualifier, arg1_type, arg1_name) \
1463471de107SMattias Rönnblom 	__RTE_BIT_OVERLOAD_SZ_2(family, fun, qualifier, 32, arg1_type, arg1_name) \
1464471de107SMattias Rönnblom 	__RTE_BIT_OVERLOAD_SZ_2(family, fun, qualifier, 64, arg1_type, arg1_name)
1465471de107SMattias Rönnblom 
1466471de107SMattias Rönnblom #define __RTE_BIT_OVERLOAD_V_2R(family, v, fun, qualifier, size, ret_type, arg1_type, arg1_name) \
1467471de107SMattias Rönnblom static inline ret_type \
1468471de107SMattias Rönnblom rte_bit_ ## family ## fun(qualifier uint ## size ## _t *addr, arg1_type arg1_name) \
1469471de107SMattias Rönnblom { \
1470471de107SMattias Rönnblom 	return __rte_bit_ ## family ## v ## fun ## size(addr, arg1_name); \
1471471de107SMattias Rönnblom }
1472471de107SMattias Rönnblom 
1473471de107SMattias Rönnblom #define __RTE_BIT_OVERLOAD_SZ_2R(family, fun, qualifier, size, ret_type, arg1_type, arg1_name) \
14740883d736SMattias Rönnblom 	__RTE_BIT_OVERLOAD_V_2R(family,, fun, qualifier, size, ret_type, arg1_type, arg1_name) \
14750883d736SMattias Rönnblom 	__RTE_BIT_OVERLOAD_V_2R(family, v_, fun, qualifier volatile, size, ret_type, arg1_type, \
14760883d736SMattias Rönnblom 		arg1_name)
1477471de107SMattias Rönnblom 
1478471de107SMattias Rönnblom #define __RTE_BIT_OVERLOAD_2R(family, fun, qualifier, ret_type, arg1_type, arg1_name) \
1479471de107SMattias Rönnblom 	__RTE_BIT_OVERLOAD_SZ_2R(family, fun, qualifier, 32, ret_type, arg1_type, arg1_name) \
1480471de107SMattias Rönnblom 	__RTE_BIT_OVERLOAD_SZ_2R(family, fun, qualifier, 64, ret_type, arg1_type, arg1_name)
1481471de107SMattias Rönnblom 
1482471de107SMattias Rönnblom #define __RTE_BIT_OVERLOAD_V_3(family, v, fun, qualifier, size, arg1_type, arg1_name, \
1483471de107SMattias Rönnblom 		arg2_type, arg2_name) \
1484471de107SMattias Rönnblom static inline void \
1485471de107SMattias Rönnblom rte_bit_ ## family ## fun(qualifier uint ## size ## _t *addr, arg1_type arg1_name, \
1486471de107SMattias Rönnblom 		arg2_type arg2_name) \
1487471de107SMattias Rönnblom { \
1488471de107SMattias Rönnblom 	__rte_bit_ ## family ## v ## fun ## size(addr, arg1_name, arg2_name); \
1489471de107SMattias Rönnblom }
1490471de107SMattias Rönnblom 
1491471de107SMattias Rönnblom #define __RTE_BIT_OVERLOAD_SZ_3(family, fun, qualifier, size, arg1_type, arg1_name, \
1492471de107SMattias Rönnblom 		arg2_type, arg2_name) \
1493471de107SMattias Rönnblom 	__RTE_BIT_OVERLOAD_V_3(family,, fun, qualifier, size, arg1_type, arg1_name, \
14940883d736SMattias Rönnblom 		arg2_type, arg2_name) \
14950883d736SMattias Rönnblom 	__RTE_BIT_OVERLOAD_V_3(family, v_, fun, qualifier volatile, size, arg1_type, arg1_name, \
1496471de107SMattias Rönnblom 		arg2_type, arg2_name)
1497471de107SMattias Rönnblom 
1498471de107SMattias Rönnblom #define __RTE_BIT_OVERLOAD_3(family, fun, qualifier, arg1_type, arg1_name, arg2_type, arg2_name) \
1499471de107SMattias Rönnblom 	__RTE_BIT_OVERLOAD_SZ_3(family, fun, qualifier, 32, arg1_type, arg1_name, \
1500471de107SMattias Rönnblom 		arg2_type, arg2_name) \
1501471de107SMattias Rönnblom 	__RTE_BIT_OVERLOAD_SZ_3(family, fun, qualifier, 64, arg1_type, arg1_name, \
1502471de107SMattias Rönnblom 		arg2_type, arg2_name)
1503471de107SMattias Rönnblom 
150435326b61SMattias Rönnblom #define __RTE_BIT_OVERLOAD_V_3R(family, v, fun, qualifier, size, ret_type, arg1_type, arg1_name, \
150535326b61SMattias Rönnblom 		arg2_type, arg2_name) \
150635326b61SMattias Rönnblom static inline ret_type \
150735326b61SMattias Rönnblom rte_bit_ ## family ## fun(qualifier uint ## size ## _t *addr, arg1_type arg1_name, \
150835326b61SMattias Rönnblom 		arg2_type arg2_name) \
150935326b61SMattias Rönnblom { \
151035326b61SMattias Rönnblom 	return __rte_bit_ ## family ## v ## fun ## size(addr, arg1_name, arg2_name); \
151135326b61SMattias Rönnblom }
151235326b61SMattias Rönnblom 
151335326b61SMattias Rönnblom #define __RTE_BIT_OVERLOAD_SZ_3R(family, fun, qualifier, size, ret_type, arg1_type, arg1_name, \
151435326b61SMattias Rönnblom 		arg2_type, arg2_name) \
151535326b61SMattias Rönnblom 	__RTE_BIT_OVERLOAD_V_3R(family,, fun, qualifier, size, ret_type, arg1_type, arg1_name, \
15160883d736SMattias Rönnblom 		arg2_type, arg2_name) \
15170883d736SMattias Rönnblom 	__RTE_BIT_OVERLOAD_V_3R(family, v_, fun, qualifier volatile, size, ret_type, \
15180883d736SMattias Rönnblom 		arg1_type, arg1_name, arg2_type, arg2_name)
151935326b61SMattias Rönnblom 
152035326b61SMattias Rönnblom #define __RTE_BIT_OVERLOAD_3R(family, fun, qualifier, ret_type, arg1_type, arg1_name, \
152135326b61SMattias Rönnblom 		arg2_type, arg2_name) \
152235326b61SMattias Rönnblom 	__RTE_BIT_OVERLOAD_SZ_3R(family, fun, qualifier, 32, ret_type, arg1_type, arg1_name, \
152335326b61SMattias Rönnblom 		arg2_type, arg2_name) \
152435326b61SMattias Rönnblom 	__RTE_BIT_OVERLOAD_SZ_3R(family, fun, qualifier, 64, ret_type, arg1_type, arg1_name, \
152535326b61SMattias Rönnblom 		arg2_type, arg2_name)
152635326b61SMattias Rönnblom 
152735326b61SMattias Rönnblom #define __RTE_BIT_OVERLOAD_V_4(family, v, fun, qualifier, size, arg1_type, arg1_name, \
152835326b61SMattias Rönnblom 		arg2_type, arg2_name, arg3_type, arg3_name) \
152935326b61SMattias Rönnblom static inline void \
153035326b61SMattias Rönnblom rte_bit_ ## family ## fun(qualifier uint ## size ## _t *addr, arg1_type arg1_name, \
153135326b61SMattias Rönnblom 		arg2_type arg2_name, arg3_type arg3_name) \
153235326b61SMattias Rönnblom { \
153335326b61SMattias Rönnblom 	__rte_bit_ ## family ## v ## fun ## size(addr, arg1_name, arg2_name, arg3_name); \
153435326b61SMattias Rönnblom }
153535326b61SMattias Rönnblom 
153635326b61SMattias Rönnblom #define __RTE_BIT_OVERLOAD_SZ_4(family, fun, qualifier, size, arg1_type, arg1_name, \
153735326b61SMattias Rönnblom 		arg2_type, arg2_name, arg3_type, arg3_name) \
153835326b61SMattias Rönnblom 	__RTE_BIT_OVERLOAD_V_4(family,, fun, qualifier, size, arg1_type, arg1_name, \
15390883d736SMattias Rönnblom 		arg2_type, arg2_name, arg3_type, arg3_name) \
15400883d736SMattias Rönnblom 	__RTE_BIT_OVERLOAD_V_4(family, v_, fun, qualifier volatile, size, arg1_type, arg1_name, \
154135326b61SMattias Rönnblom 		arg2_type, arg2_name, arg3_type, arg3_name)
154235326b61SMattias Rönnblom 
154335326b61SMattias Rönnblom #define __RTE_BIT_OVERLOAD_4(family, fun, qualifier, arg1_type, arg1_name, arg2_type, arg2_name, \
154435326b61SMattias Rönnblom 		arg3_type, arg3_name) \
154535326b61SMattias Rönnblom 	__RTE_BIT_OVERLOAD_SZ_4(family, fun, qualifier, 32, arg1_type, arg1_name, \
154635326b61SMattias Rönnblom 		arg2_type, arg2_name, arg3_type, arg3_name) \
154735326b61SMattias Rönnblom 	__RTE_BIT_OVERLOAD_SZ_4(family, fun, qualifier, 64, arg1_type, arg1_name, \
154835326b61SMattias Rönnblom 		arg2_type, arg2_name, arg3_type, arg3_name)
154935326b61SMattias Rönnblom 
155035326b61SMattias Rönnblom #define __RTE_BIT_OVERLOAD_V_4R(family, v, fun, qualifier, size, ret_type, arg1_type, arg1_name, \
155135326b61SMattias Rönnblom 		arg2_type, arg2_name, arg3_type, arg3_name) \
155235326b61SMattias Rönnblom static inline ret_type \
155335326b61SMattias Rönnblom rte_bit_ ## family ## fun(qualifier uint ## size ## _t *addr, arg1_type arg1_name, \
155435326b61SMattias Rönnblom 		arg2_type arg2_name, arg3_type arg3_name) \
155535326b61SMattias Rönnblom { \
155635326b61SMattias Rönnblom 	return __rte_bit_ ## family ## v ## fun ## size(addr, arg1_name, arg2_name, \
155735326b61SMattias Rönnblom 		arg3_name); \
155835326b61SMattias Rönnblom }
155935326b61SMattias Rönnblom 
156035326b61SMattias Rönnblom #define __RTE_BIT_OVERLOAD_SZ_4R(family, fun, qualifier, size, ret_type, arg1_type, arg1_name, \
156135326b61SMattias Rönnblom 		arg2_type, arg2_name, arg3_type, arg3_name) \
156235326b61SMattias Rönnblom 	__RTE_BIT_OVERLOAD_V_4R(family,, fun, qualifier, size, ret_type, arg1_type, arg1_name, \
15630883d736SMattias Rönnblom 		arg2_type, arg2_name, arg3_type, arg3_name) \
15640883d736SMattias Rönnblom 	__RTE_BIT_OVERLOAD_V_4R(family, v_, fun, qualifier volatile, size, ret_type, \
15650883d736SMattias Rönnblom 		arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name)
156635326b61SMattias Rönnblom 
156735326b61SMattias Rönnblom #define __RTE_BIT_OVERLOAD_4R(family, fun, qualifier, ret_type, arg1_type, arg1_name, \
156835326b61SMattias Rönnblom 		arg2_type, arg2_name, arg3_type, arg3_name) \
156935326b61SMattias Rönnblom 	__RTE_BIT_OVERLOAD_SZ_4R(family, fun, qualifier, 32, ret_type, arg1_type, arg1_name, \
157035326b61SMattias Rönnblom 		arg2_type, arg2_name, arg3_type, arg3_name) \
157135326b61SMattias Rönnblom 	__RTE_BIT_OVERLOAD_SZ_4R(family, fun, qualifier, 64, ret_type, arg1_type, arg1_name, \
157235326b61SMattias Rönnblom 		arg2_type, arg2_name, arg3_type, arg3_name)
157335326b61SMattias Rönnblom 
15748b65ddc0SDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API
1575471de107SMattias Rönnblom __RTE_BIT_OVERLOAD_2R(, test, const, bool, unsigned int, nr)
1576471de107SMattias Rönnblom __RTE_BIT_OVERLOAD_2(, set,, unsigned int, nr)
1577471de107SMattias Rönnblom __RTE_BIT_OVERLOAD_2(, clear,, unsigned int, nr)
1578471de107SMattias Rönnblom __RTE_BIT_OVERLOAD_3(, assign,, unsigned int, nr, bool, value)
1579471de107SMattias Rönnblom __RTE_BIT_OVERLOAD_2(, flip,, unsigned int, nr)
1580471de107SMattias Rönnblom 
158135326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_3R(atomic_, test, const, bool, unsigned int, nr, int, memory_order)
158235326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_3(atomic_, set,, unsigned int, nr, int, memory_order)
158335326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_3(atomic_, clear,, unsigned int, nr, int, memory_order)
158435326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_4(atomic_, assign,, unsigned int, nr, bool, value, int, memory_order)
158535326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_3(atomic_, flip,, unsigned int, nr, int, memory_order)
158635326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_3R(atomic_, test_and_set,, bool, unsigned int, nr, int, memory_order)
158735326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_3R(atomic_, test_and_clear,, bool, unsigned int, nr, int, memory_order)
158835326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_4R(atomic_, test_and_assign,, bool, unsigned int, nr, bool, value,
158935326b61SMattias Rönnblom 	int, memory_order)
15908b65ddc0SDavid Marchand #endif
159135326b61SMattias Rönnblom 
1592d7e9c02cSBrian Dooley #endif
1593d7e9c02cSBrian Dooley 
159499a2dd95SBruce Richardson #endif /* _RTE_BITOPS_H_ */
1595