xref: /openbmc/u-boot/arch/riscv/include/asm/bitops.h (revision accdce5f86084be63eebc970532513f063115a8e)
16020faf6SRick Chen /*
26020faf6SRick Chen  * Copyright 1995, Russell King.
36020faf6SRick Chen  * Various bits and pieces copyrights include:
46020faf6SRick Chen  * Linus Torvalds (test_bit).
56020faf6SRick Chen  *
66020faf6SRick Chen  * Copyright (C) 2017 Andes Technology Corporation
76020faf6SRick Chen  * Rick Chen, Andes Technology Corporation <rick@andestech.com>
86020faf6SRick Chen  *
96020faf6SRick Chen  * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
106020faf6SRick Chen  *
116020faf6SRick Chen  * Please note that the code in this file should never be included
126020faf6SRick Chen  * from user space.  Many of these are not implemented in assembler
136020faf6SRick Chen  * since they would be too costly.  Also, they require priviledged
146020faf6SRick Chen  * instructions (which are not available from user mode) to ensure
156020faf6SRick Chen  * that they are atomic.
166020faf6SRick Chen  */
176020faf6SRick Chen 
186020faf6SRick Chen #ifndef __ASM_RISCV_BITOPS_H
196020faf6SRick Chen #define __ASM_RISCV_BITOPS_H
206020faf6SRick Chen 
216020faf6SRick Chen #ifdef __KERNEL__
226020faf6SRick Chen 
236020faf6SRick Chen #include <asm/system.h>
246020faf6SRick Chen #include <asm-generic/bitops/fls.h>
256020faf6SRick Chen #include <asm-generic/bitops/__fls.h>
266020faf6SRick Chen #include <asm-generic/bitops/fls64.h>
276020faf6SRick Chen #include <asm-generic/bitops/__ffs.h>
286020faf6SRick Chen 
296020faf6SRick Chen #define smp_mb__before_clear_bit()	do { } while (0)
306020faf6SRick Chen #define smp_mb__after_clear_bit()	do { } while (0)
316020faf6SRick Chen 
326020faf6SRick Chen /*
336020faf6SRick Chen  * Function prototypes to keep gcc -Wall happy.
346020faf6SRick Chen  */
__set_bit(int nr,void * addr)356020faf6SRick Chen static inline void __set_bit(int nr, void *addr)
366020faf6SRick Chen {
376020faf6SRick Chen 	int *a = (int *)addr;
386020faf6SRick Chen 	int mask;
396020faf6SRick Chen 
406020faf6SRick Chen 	a += nr >> 5;
416020faf6SRick Chen 	mask = 1 << (nr & 0x1f);
426020faf6SRick Chen 	*a |= mask;
436020faf6SRick Chen }
446020faf6SRick Chen 
45820cba2cSBryan O'Donoghue #define PLATFORM__SET_BIT
46820cba2cSBryan O'Donoghue 
__clear_bit(int nr,void * addr)476020faf6SRick Chen static inline void __clear_bit(int nr, void *addr)
486020faf6SRick Chen {
496020faf6SRick Chen 	int *a = (int *)addr;
506020faf6SRick Chen 	int mask;
516020faf6SRick Chen 
526020faf6SRick Chen 	a += nr >> 5;
536020faf6SRick Chen 	mask = 1 << (nr & 0x1f);
546020faf6SRick Chen 	*a &= ~mask;
556020faf6SRick Chen }
566020faf6SRick Chen 
57*accdce5fSBryan O'Donoghue #define PLATFORM__CLEAR_BIT
58*accdce5fSBryan O'Donoghue 
__change_bit(int nr,void * addr)596020faf6SRick Chen static inline void __change_bit(int nr, void *addr)
606020faf6SRick Chen {
616020faf6SRick Chen 	int mask;
626020faf6SRick Chen 	unsigned long *ADDR = (unsigned long *)addr;
636020faf6SRick Chen 
646020faf6SRick Chen 	ADDR += nr >> 5;
656020faf6SRick Chen 	mask = 1 << (nr & 31);
666020faf6SRick Chen 	*ADDR ^= mask;
676020faf6SRick Chen }
686020faf6SRick Chen 
__test_and_set_bit(int nr,void * addr)696020faf6SRick Chen static inline int __test_and_set_bit(int nr, void *addr)
706020faf6SRick Chen {
716020faf6SRick Chen 	int mask, retval;
726020faf6SRick Chen 	unsigned int *a = (unsigned int *)addr;
736020faf6SRick Chen 
746020faf6SRick Chen 	a += nr >> 5;
756020faf6SRick Chen 	mask = 1 << (nr & 0x1f);
766020faf6SRick Chen 	retval = (mask & *a) != 0;
776020faf6SRick Chen 	*a |= mask;
786020faf6SRick Chen 	return retval;
796020faf6SRick Chen }
806020faf6SRick Chen 
__test_and_clear_bit(int nr,void * addr)816020faf6SRick Chen static inline int __test_and_clear_bit(int nr, void *addr)
826020faf6SRick Chen {
836020faf6SRick Chen 	int mask, retval;
846020faf6SRick Chen 	unsigned int *a = (unsigned int *)addr;
856020faf6SRick Chen 
866020faf6SRick Chen 	a += nr >> 5;
876020faf6SRick Chen 	mask = 1 << (nr & 0x1f);
886020faf6SRick Chen 	retval = (mask & *a) != 0;
896020faf6SRick Chen 	*a &= ~mask;
906020faf6SRick Chen 	return retval;
916020faf6SRick Chen }
926020faf6SRick Chen 
__test_and_change_bit(int nr,void * addr)936020faf6SRick Chen static inline int __test_and_change_bit(int nr, void *addr)
946020faf6SRick Chen {
956020faf6SRick Chen 	int mask, retval;
966020faf6SRick Chen 	unsigned int *a = (unsigned int *)addr;
976020faf6SRick Chen 
986020faf6SRick Chen 	a += nr >> 5;
996020faf6SRick Chen 	mask = 1 << (nr & 0x1f);
1006020faf6SRick Chen 	retval = (mask & *a) != 0;
1016020faf6SRick Chen 	*a ^= mask;
1026020faf6SRick Chen 	return retval;
1036020faf6SRick Chen }
1046020faf6SRick Chen 
1056020faf6SRick Chen /*
1066020faf6SRick Chen  * This routine doesn't need to be atomic.
1076020faf6SRick Chen  */
test_bit(int nr,const void * addr)1086020faf6SRick Chen static inline int test_bit(int nr, const void *addr)
1096020faf6SRick Chen {
1106020faf6SRick Chen 	return ((unsigned char *)addr)[nr >> 3] & (1U << (nr & 7));
1116020faf6SRick Chen }
1126020faf6SRick Chen 
1136020faf6SRick Chen /*
1146020faf6SRick Chen  * ffz = Find First Zero in word. Undefined if no zero exists,
1156020faf6SRick Chen  * so code should check against ~0UL first..
1166020faf6SRick Chen  */
ffz(unsigned long word)1176020faf6SRick Chen static inline unsigned long ffz(unsigned long word)
1186020faf6SRick Chen {
1196020faf6SRick Chen 	int k;
1206020faf6SRick Chen 
1216020faf6SRick Chen 	word = ~word;
1226020faf6SRick Chen 	k = 31;
1236020faf6SRick Chen 	if (word & 0x0000ffff) {
1246020faf6SRick Chen 		k -= 16; word <<= 16;
1256020faf6SRick Chen 	}
1266020faf6SRick Chen 	if (word & 0x00ff0000) {
1276020faf6SRick Chen 		k -= 8;  word <<= 8;
1286020faf6SRick Chen 	}
1296020faf6SRick Chen 	if (word & 0x0f000000) {
1306020faf6SRick Chen 		k -= 4;  word <<= 4;
1316020faf6SRick Chen 	}
1326020faf6SRick Chen 	if (word & 0x30000000) {
1336020faf6SRick Chen 		k -= 2;  word <<= 2;
1346020faf6SRick Chen 	}
1356020faf6SRick Chen 	if (word & 0x40000000)
1366020faf6SRick Chen 		k -= 1;
1376020faf6SRick Chen 
1386020faf6SRick Chen 	return k;
1396020faf6SRick Chen }
1406020faf6SRick Chen 
1416020faf6SRick Chen /*
1426020faf6SRick Chen  * ffs: find first bit set. This is defined the same way as
1436020faf6SRick Chen  * the libc and compiler builtin ffs routines, therefore
1446020faf6SRick Chen  * differs in spirit from the above ffz (man ffs).
1456020faf6SRick Chen  */
1466020faf6SRick Chen 
1476020faf6SRick Chen /*
1486020faf6SRick Chen  * redefined in include/linux/bitops.h
1496020faf6SRick Chen  * #define ffs(x) generic_ffs(x)
1506020faf6SRick Chen  */
1516020faf6SRick Chen 
1526020faf6SRick Chen /*
1536020faf6SRick Chen  * hweightN: returns the hamming weight (i.e. the number
1546020faf6SRick Chen  * of bits set) of a N-bit word
1556020faf6SRick Chen  */
1566020faf6SRick Chen 
1576020faf6SRick Chen #define hweight32(x) generic_hweight32(x)
1586020faf6SRick Chen #define hweight16(x) generic_hweight16(x)
1596020faf6SRick Chen #define hweight8(x) generic_hweight8(x)
1606020faf6SRick Chen 
1616020faf6SRick Chen #define ext2_set_bit			test_and_set_bit
1626020faf6SRick Chen #define ext2_clear_bit			test_and_clear_bit
1636020faf6SRick Chen #define ext2_test_bit			test_bit
1646020faf6SRick Chen #define ext2_find_first_zero_bit	find_first_zero_bit
1656020faf6SRick Chen #define ext2_find_next_zero_bit		find_next_zero_bit
1666020faf6SRick Chen 
1676020faf6SRick Chen /* Bitmap functions for the minix filesystem. */
1686020faf6SRick Chen #define minix_test_and_set_bit(nr, addr)	test_and_set_bit(nr, addr)
1696020faf6SRick Chen #define minix_set_bit(nr, addr)			set_bit(nr, addr)
1706020faf6SRick Chen #define minix_test_and_clear_bit(nr, addr)	test_and_clear_bit(nr, addr)
1716020faf6SRick Chen #define minix_test_bit(nr, addr)		test_bit(nr, addr)
1726020faf6SRick Chen #define minix_find_first_zero_bit(addr, size)	find_first_zero_bit(addr, size)
1736020faf6SRick Chen 
1746020faf6SRick Chen #endif /* __KERNEL__ */
1756020faf6SRick Chen 
1766020faf6SRick Chen #endif /* __ASM_RISCV_BITOPS_H */
177