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