xref: /openbmc/linux/arch/riscv/include/asm/bitops.h (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
1*50acfb2bSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
2fab957c1SPalmer Dabbelt /*
3fab957c1SPalmer Dabbelt  * Copyright (C) 2012 Regents of the University of California
4fab957c1SPalmer Dabbelt  */
5fab957c1SPalmer Dabbelt 
6fab957c1SPalmer Dabbelt #ifndef _ASM_RISCV_BITOPS_H
7fab957c1SPalmer Dabbelt #define _ASM_RISCV_BITOPS_H
8fab957c1SPalmer Dabbelt 
9fab957c1SPalmer Dabbelt #ifndef _LINUX_BITOPS_H
10fab957c1SPalmer Dabbelt #error "Only <linux/bitops.h> can be included directly"
11fab957c1SPalmer Dabbelt #endif /* _LINUX_BITOPS_H */
12fab957c1SPalmer Dabbelt 
13fab957c1SPalmer Dabbelt #include <linux/compiler.h>
14fab957c1SPalmer Dabbelt #include <linux/irqflags.h>
15fab957c1SPalmer Dabbelt #include <asm/barrier.h>
16fab957c1SPalmer Dabbelt #include <asm/bitsperlong.h>
17fab957c1SPalmer Dabbelt 
18fab957c1SPalmer Dabbelt #include <asm-generic/bitops/__ffs.h>
19fab957c1SPalmer Dabbelt #include <asm-generic/bitops/ffz.h>
20fab957c1SPalmer Dabbelt #include <asm-generic/bitops/fls.h>
21fab957c1SPalmer Dabbelt #include <asm-generic/bitops/__fls.h>
22fab957c1SPalmer Dabbelt #include <asm-generic/bitops/fls64.h>
23fab957c1SPalmer Dabbelt #include <asm-generic/bitops/sched.h>
24fab957c1SPalmer Dabbelt #include <asm-generic/bitops/ffs.h>
25fab957c1SPalmer Dabbelt 
26fab957c1SPalmer Dabbelt #include <asm-generic/bitops/hweight.h>
27fab957c1SPalmer Dabbelt 
28fab957c1SPalmer Dabbelt #if (BITS_PER_LONG == 64)
29fab957c1SPalmer Dabbelt #define __AMO(op)	"amo" #op ".d"
30fab957c1SPalmer Dabbelt #elif (BITS_PER_LONG == 32)
31fab957c1SPalmer Dabbelt #define __AMO(op)	"amo" #op ".w"
32fab957c1SPalmer Dabbelt #else
33fab957c1SPalmer Dabbelt #error "Unexpected BITS_PER_LONG"
34fab957c1SPalmer Dabbelt #endif
35fab957c1SPalmer Dabbelt 
36fab957c1SPalmer Dabbelt #define __test_and_op_bit_ord(op, mod, nr, addr, ord)		\
37fab957c1SPalmer Dabbelt ({								\
38fab957c1SPalmer Dabbelt 	unsigned long __res, __mask;				\
39fab957c1SPalmer Dabbelt 	__mask = BIT_MASK(nr);					\
40fab957c1SPalmer Dabbelt 	__asm__ __volatile__ (					\
41fab957c1SPalmer Dabbelt 		__AMO(op) #ord " %0, %2, %1"			\
42fab957c1SPalmer Dabbelt 		: "=r" (__res), "+A" (addr[BIT_WORD(nr)])	\
43fab957c1SPalmer Dabbelt 		: "r" (mod(__mask))				\
44fab957c1SPalmer Dabbelt 		: "memory");					\
45fab957c1SPalmer Dabbelt 	((__res & __mask) != 0);				\
46fab957c1SPalmer Dabbelt })
47fab957c1SPalmer Dabbelt 
48fab957c1SPalmer Dabbelt #define __op_bit_ord(op, mod, nr, addr, ord)			\
49fab957c1SPalmer Dabbelt 	__asm__ __volatile__ (					\
50fab957c1SPalmer Dabbelt 		__AMO(op) #ord " zero, %1, %0"			\
51fab957c1SPalmer Dabbelt 		: "+A" (addr[BIT_WORD(nr)])			\
52fab957c1SPalmer Dabbelt 		: "r" (mod(BIT_MASK(nr)))			\
53fab957c1SPalmer Dabbelt 		: "memory");
54fab957c1SPalmer Dabbelt 
55fab957c1SPalmer Dabbelt #define __test_and_op_bit(op, mod, nr, addr) 			\
569347ce54SPalmer Dabbelt 	__test_and_op_bit_ord(op, mod, nr, addr, .aqrl)
57fab957c1SPalmer Dabbelt #define __op_bit(op, mod, nr, addr)				\
58fab957c1SPalmer Dabbelt 	__op_bit_ord(op, mod, nr, addr, )
59fab957c1SPalmer Dabbelt 
60fab957c1SPalmer Dabbelt /* Bitmask modifiers */
61fab957c1SPalmer Dabbelt #define __NOP(x)	(x)
62fab957c1SPalmer Dabbelt #define __NOT(x)	(~(x))
63fab957c1SPalmer Dabbelt 
64fab957c1SPalmer Dabbelt /**
65fab957c1SPalmer Dabbelt  * test_and_set_bit - Set a bit and return its old value
66fab957c1SPalmer Dabbelt  * @nr: Bit to set
67fab957c1SPalmer Dabbelt  * @addr: Address to count from
68fab957c1SPalmer Dabbelt  *
69fab957c1SPalmer Dabbelt  * This operation may be reordered on other architectures than x86.
70fab957c1SPalmer Dabbelt  */
test_and_set_bit(int nr,volatile unsigned long * addr)71fab957c1SPalmer Dabbelt static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
72fab957c1SPalmer Dabbelt {
73fab957c1SPalmer Dabbelt 	return __test_and_op_bit(or, __NOP, nr, addr);
74fab957c1SPalmer Dabbelt }
75fab957c1SPalmer Dabbelt 
76fab957c1SPalmer Dabbelt /**
77fab957c1SPalmer Dabbelt  * test_and_clear_bit - Clear a bit and return its old value
78fab957c1SPalmer Dabbelt  * @nr: Bit to clear
79fab957c1SPalmer Dabbelt  * @addr: Address to count from
80fab957c1SPalmer Dabbelt  *
81fab957c1SPalmer Dabbelt  * This operation can be reordered on other architectures other than x86.
82fab957c1SPalmer Dabbelt  */
test_and_clear_bit(int nr,volatile unsigned long * addr)83fab957c1SPalmer Dabbelt static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
84fab957c1SPalmer Dabbelt {
85fab957c1SPalmer Dabbelt 	return __test_and_op_bit(and, __NOT, nr, addr);
86fab957c1SPalmer Dabbelt }
87fab957c1SPalmer Dabbelt 
88fab957c1SPalmer Dabbelt /**
89fab957c1SPalmer Dabbelt  * test_and_change_bit - Change a bit and return its old value
90fab957c1SPalmer Dabbelt  * @nr: Bit to change
91fab957c1SPalmer Dabbelt  * @addr: Address to count from
92fab957c1SPalmer Dabbelt  *
93fab957c1SPalmer Dabbelt  * This operation is atomic and cannot be reordered.
94fab957c1SPalmer Dabbelt  * It also implies a memory barrier.
95fab957c1SPalmer Dabbelt  */
test_and_change_bit(int nr,volatile unsigned long * addr)96fab957c1SPalmer Dabbelt static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
97fab957c1SPalmer Dabbelt {
98fab957c1SPalmer Dabbelt 	return __test_and_op_bit(xor, __NOP, nr, addr);
99fab957c1SPalmer Dabbelt }
100fab957c1SPalmer Dabbelt 
101fab957c1SPalmer Dabbelt /**
102fab957c1SPalmer Dabbelt  * set_bit - Atomically set a bit in memory
103fab957c1SPalmer Dabbelt  * @nr: the bit to set
104fab957c1SPalmer Dabbelt  * @addr: the address to start counting from
105fab957c1SPalmer Dabbelt  *
106fab957c1SPalmer Dabbelt  * Note: there are no guarantees that this function will not be reordered
107fab957c1SPalmer Dabbelt  * on non x86 architectures, so if you are writing portable code,
108fab957c1SPalmer Dabbelt  * make sure not to rely on its reordering guarantees.
109fab957c1SPalmer Dabbelt  *
110fab957c1SPalmer Dabbelt  * Note that @nr may be almost arbitrarily large; this function is not
111fab957c1SPalmer Dabbelt  * restricted to acting on a single-word quantity.
112fab957c1SPalmer Dabbelt  */
set_bit(int nr,volatile unsigned long * addr)113fab957c1SPalmer Dabbelt static inline void set_bit(int nr, volatile unsigned long *addr)
114fab957c1SPalmer Dabbelt {
115fab957c1SPalmer Dabbelt 	__op_bit(or, __NOP, nr, addr);
116fab957c1SPalmer Dabbelt }
117fab957c1SPalmer Dabbelt 
118fab957c1SPalmer Dabbelt /**
119fab957c1SPalmer Dabbelt  * clear_bit - Clears a bit in memory
120fab957c1SPalmer Dabbelt  * @nr: Bit to clear
121fab957c1SPalmer Dabbelt  * @addr: Address to start counting from
122fab957c1SPalmer Dabbelt  *
123fab957c1SPalmer Dabbelt  * Note: there are no guarantees that this function will not be reordered
124fab957c1SPalmer Dabbelt  * on non x86 architectures, so if you are writing portable code,
125fab957c1SPalmer Dabbelt  * make sure not to rely on its reordering guarantees.
126fab957c1SPalmer Dabbelt  */
clear_bit(int nr,volatile unsigned long * addr)127fab957c1SPalmer Dabbelt static inline void clear_bit(int nr, volatile unsigned long *addr)
128fab957c1SPalmer Dabbelt {
129fab957c1SPalmer Dabbelt 	__op_bit(and, __NOT, nr, addr);
130fab957c1SPalmer Dabbelt }
131fab957c1SPalmer Dabbelt 
132fab957c1SPalmer Dabbelt /**
133fab957c1SPalmer Dabbelt  * change_bit - Toggle a bit in memory
134fab957c1SPalmer Dabbelt  * @nr: Bit to change
135fab957c1SPalmer Dabbelt  * @addr: Address to start counting from
136fab957c1SPalmer Dabbelt  *
137fab957c1SPalmer Dabbelt  * change_bit()  may be reordered on other architectures than x86.
138fab957c1SPalmer Dabbelt  * Note that @nr may be almost arbitrarily large; this function is not
139fab957c1SPalmer Dabbelt  * restricted to acting on a single-word quantity.
140fab957c1SPalmer Dabbelt  */
change_bit(int nr,volatile unsigned long * addr)141fab957c1SPalmer Dabbelt static inline void change_bit(int nr, volatile unsigned long *addr)
142fab957c1SPalmer Dabbelt {
143fab957c1SPalmer Dabbelt 	__op_bit(xor, __NOP, nr, addr);
144fab957c1SPalmer Dabbelt }
145fab957c1SPalmer Dabbelt 
146fab957c1SPalmer Dabbelt /**
147fab957c1SPalmer Dabbelt  * test_and_set_bit_lock - Set a bit and return its old value, for lock
148fab957c1SPalmer Dabbelt  * @nr: Bit to set
149fab957c1SPalmer Dabbelt  * @addr: Address to count from
150fab957c1SPalmer Dabbelt  *
151fab957c1SPalmer Dabbelt  * This operation is atomic and provides acquire barrier semantics.
152fab957c1SPalmer Dabbelt  * It can be used to implement bit locks.
153fab957c1SPalmer Dabbelt  */
test_and_set_bit_lock(unsigned long nr,volatile unsigned long * addr)154fab957c1SPalmer Dabbelt static inline int test_and_set_bit_lock(
155fab957c1SPalmer Dabbelt 	unsigned long nr, volatile unsigned long *addr)
156fab957c1SPalmer Dabbelt {
157fab957c1SPalmer Dabbelt 	return __test_and_op_bit_ord(or, __NOP, nr, addr, .aq);
158fab957c1SPalmer Dabbelt }
159fab957c1SPalmer Dabbelt 
160fab957c1SPalmer Dabbelt /**
161fab957c1SPalmer Dabbelt  * clear_bit_unlock - Clear a bit in memory, for unlock
162fab957c1SPalmer Dabbelt  * @nr: the bit to set
163fab957c1SPalmer Dabbelt  * @addr: the address to start counting from
164fab957c1SPalmer Dabbelt  *
165fab957c1SPalmer Dabbelt  * This operation is atomic and provides release barrier semantics.
166fab957c1SPalmer Dabbelt  */
clear_bit_unlock(unsigned long nr,volatile unsigned long * addr)167fab957c1SPalmer Dabbelt static inline void clear_bit_unlock(
168fab957c1SPalmer Dabbelt 	unsigned long nr, volatile unsigned long *addr)
169fab957c1SPalmer Dabbelt {
170fab957c1SPalmer Dabbelt 	__op_bit_ord(and, __NOT, nr, addr, .rl);
171fab957c1SPalmer Dabbelt }
172fab957c1SPalmer Dabbelt 
173fab957c1SPalmer Dabbelt /**
174fab957c1SPalmer Dabbelt  * __clear_bit_unlock - Clear a bit in memory, for unlock
175fab957c1SPalmer Dabbelt  * @nr: the bit to set
176fab957c1SPalmer Dabbelt  * @addr: the address to start counting from
177fab957c1SPalmer Dabbelt  *
178fab957c1SPalmer Dabbelt  * This operation is like clear_bit_unlock, however it is not atomic.
179fab957c1SPalmer Dabbelt  * It does provide release barrier semantics so it can be used to unlock
180fab957c1SPalmer Dabbelt  * a bit lock, however it would only be used if no other CPU can modify
181fab957c1SPalmer Dabbelt  * any bits in the memory until the lock is released (a good example is
182fab957c1SPalmer Dabbelt  * if the bit lock itself protects access to the other bits in the word).
183fab957c1SPalmer Dabbelt  *
184fab957c1SPalmer Dabbelt  * On RISC-V systems there seems to be no benefit to taking advantage of the
185fab957c1SPalmer Dabbelt  * non-atomic property here: it's a lot more instructions and we still have to
186fab957c1SPalmer Dabbelt  * provide release semantics anyway.
187fab957c1SPalmer Dabbelt  */
__clear_bit_unlock(unsigned long nr,volatile unsigned long * addr)188fab957c1SPalmer Dabbelt static inline void __clear_bit_unlock(
189fab957c1SPalmer Dabbelt 	unsigned long nr, volatile unsigned long *addr)
190fab957c1SPalmer Dabbelt {
191fab957c1SPalmer Dabbelt 	clear_bit_unlock(nr, addr);
192fab957c1SPalmer Dabbelt }
193fab957c1SPalmer Dabbelt 
194fab957c1SPalmer Dabbelt #undef __test_and_op_bit
195fab957c1SPalmer Dabbelt #undef __op_bit
196fab957c1SPalmer Dabbelt #undef __NOP
197fab957c1SPalmer Dabbelt #undef __NOT
198fab957c1SPalmer Dabbelt #undef __AMO
199fab957c1SPalmer Dabbelt 
200fab957c1SPalmer Dabbelt #include <asm-generic/bitops/non-atomic.h>
201fab957c1SPalmer Dabbelt #include <asm-generic/bitops/le.h>
202fab957c1SPalmer Dabbelt #include <asm-generic/bitops/ext2-atomic.h>
203fab957c1SPalmer Dabbelt 
204fab957c1SPalmer Dabbelt #endif /* _ASM_RISCV_BITOPS_H */
205