1367b8112SChris Zankel /* 2367b8112SChris Zankel * include/asm-xtensa/bitops.h 3367b8112SChris Zankel * 4367b8112SChris Zankel * Atomic operations that C can't guarantee us.Useful for resource counting etc. 5367b8112SChris Zankel * 6367b8112SChris Zankel * This file is subject to the terms and conditions of the GNU General Public 7367b8112SChris Zankel * License. See the file "COPYING" in the main directory of this archive 8367b8112SChris Zankel * for more details. 9367b8112SChris Zankel * 10367b8112SChris Zankel * Copyright (C) 2001 - 2007 Tensilica Inc. 11367b8112SChris Zankel */ 12367b8112SChris Zankel 13367b8112SChris Zankel #ifndef _XTENSA_BITOPS_H 14367b8112SChris Zankel #define _XTENSA_BITOPS_H 15367b8112SChris Zankel 16367b8112SChris Zankel #ifdef __KERNEL__ 17367b8112SChris Zankel 18367b8112SChris Zankel #ifndef _LINUX_BITOPS_H 19367b8112SChris Zankel #error only <linux/bitops.h> can be included directly 20367b8112SChris Zankel #endif 21367b8112SChris Zankel 22367b8112SChris Zankel #include <asm/processor.h> 23367b8112SChris Zankel #include <asm/byteorder.h> 2409a01c0cSPeter Zijlstra #include <asm/barrier.h> 25367b8112SChris Zankel 26367b8112SChris Zankel #include <asm-generic/bitops/non-atomic.h> 27367b8112SChris Zankel 28367b8112SChris Zankel #if XCHAL_HAVE_NSA 29367b8112SChris Zankel 30367b8112SChris Zankel static inline unsigned long __cntlz (unsigned long x) 31367b8112SChris Zankel { 32367b8112SChris Zankel int lz; 33367b8112SChris Zankel asm ("nsau %0, %1" : "=r" (lz) : "r" (x)); 34367b8112SChris Zankel return lz; 35367b8112SChris Zankel } 36367b8112SChris Zankel 37367b8112SChris Zankel /* 38367b8112SChris Zankel * ffz: Find first zero in word. Undefined if no zero exists. 39367b8112SChris Zankel * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). 40367b8112SChris Zankel */ 41367b8112SChris Zankel 42367b8112SChris Zankel static inline int ffz(unsigned long x) 43367b8112SChris Zankel { 44367b8112SChris Zankel return 31 - __cntlz(~x & -~x); 45367b8112SChris Zankel } 46367b8112SChris Zankel 47367b8112SChris Zankel /* 48367b8112SChris Zankel * __ffs: Find first bit set in word. Return 0 for bit 0 49367b8112SChris Zankel */ 50367b8112SChris Zankel 51367b8112SChris Zankel static inline int __ffs(unsigned long x) 52367b8112SChris Zankel { 53367b8112SChris Zankel return 31 - __cntlz(x & -x); 54367b8112SChris Zankel } 55367b8112SChris Zankel 56367b8112SChris Zankel /* 57367b8112SChris Zankel * ffs: Find first bit set in word. This is defined the same way as 58367b8112SChris Zankel * the libc and compiler builtin ffs routines, therefore 59367b8112SChris Zankel * differs in spirit from the above ffz (man ffs). 60367b8112SChris Zankel */ 61367b8112SChris Zankel 62367b8112SChris Zankel static inline int ffs(unsigned long x) 63367b8112SChris Zankel { 64367b8112SChris Zankel return 32 - __cntlz(x & -x); 65367b8112SChris Zankel } 66367b8112SChris Zankel 67367b8112SChris Zankel /* 68367b8112SChris Zankel * fls: Find last (most-significant) bit set in word. 69367b8112SChris Zankel * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. 70367b8112SChris Zankel */ 71367b8112SChris Zankel 72367b8112SChris Zankel static inline int fls (unsigned int x) 73367b8112SChris Zankel { 74367b8112SChris Zankel return 32 - __cntlz(x); 75367b8112SChris Zankel } 76367b8112SChris Zankel 7752fefcecSLinus Torvalds /** 7852fefcecSLinus Torvalds * __fls - find last (most-significant) set bit in a long word 7952fefcecSLinus Torvalds * @word: the word to search 8052fefcecSLinus Torvalds * 8152fefcecSLinus Torvalds * Undefined if no set bit exists, so code should check against 0 first. 8252fefcecSLinus Torvalds */ 8352fefcecSLinus Torvalds static inline unsigned long __fls(unsigned long word) 8452fefcecSLinus Torvalds { 8552fefcecSLinus Torvalds return 31 - __cntlz(word); 8652fefcecSLinus Torvalds } 87367b8112SChris Zankel #else 88367b8112SChris Zankel 89367b8112SChris Zankel /* Use the generic implementation if we don't have the nsa/nsau instructions. */ 90367b8112SChris Zankel 91367b8112SChris Zankel # include <asm-generic/bitops/ffs.h> 92367b8112SChris Zankel # include <asm-generic/bitops/__ffs.h> 93367b8112SChris Zankel # include <asm-generic/bitops/ffz.h> 94367b8112SChris Zankel # include <asm-generic/bitops/fls.h> 9552fefcecSLinus Torvalds # include <asm-generic/bitops/__fls.h> 96367b8112SChris Zankel 97367b8112SChris Zankel #endif 98367b8112SChris Zankel 99367b8112SChris Zankel #include <asm-generic/bitops/fls64.h> 100e5a9f6adSMax Filippov 101e5a9f6adSMax Filippov #if XCHAL_HAVE_S32C1I 102e5a9f6adSMax Filippov 103e5a9f6adSMax Filippov static inline void set_bit(unsigned int bit, volatile unsigned long *p) 104e5a9f6adSMax Filippov { 105e5a9f6adSMax Filippov unsigned long tmp, value; 106e5a9f6adSMax Filippov unsigned long mask = 1UL << (bit & 31); 107e5a9f6adSMax Filippov 108e5a9f6adSMax Filippov p += bit >> 5; 109e5a9f6adSMax Filippov 110e5a9f6adSMax Filippov __asm__ __volatile__( 111e5a9f6adSMax Filippov "1: l32i %1, %3, 0\n" 112e5a9f6adSMax Filippov " wsr %1, scompare1\n" 113e5a9f6adSMax Filippov " or %0, %1, %2\n" 114e5a9f6adSMax Filippov " s32c1i %0, %3, 0\n" 115e5a9f6adSMax Filippov " bne %0, %1, 1b\n" 116e5a9f6adSMax Filippov : "=&a" (tmp), "=&a" (value) 117e5a9f6adSMax Filippov : "a" (mask), "a" (p) 118e5a9f6adSMax Filippov : "memory"); 119e5a9f6adSMax Filippov } 120e5a9f6adSMax Filippov 121e5a9f6adSMax Filippov static inline void clear_bit(unsigned int bit, volatile unsigned long *p) 122e5a9f6adSMax Filippov { 123e5a9f6adSMax Filippov unsigned long tmp, value; 124e5a9f6adSMax Filippov unsigned long mask = 1UL << (bit & 31); 125e5a9f6adSMax Filippov 126e5a9f6adSMax Filippov p += bit >> 5; 127e5a9f6adSMax Filippov 128e5a9f6adSMax Filippov __asm__ __volatile__( 129e5a9f6adSMax Filippov "1: l32i %1, %3, 0\n" 130e5a9f6adSMax Filippov " wsr %1, scompare1\n" 131e5a9f6adSMax Filippov " and %0, %1, %2\n" 132e5a9f6adSMax Filippov " s32c1i %0, %3, 0\n" 133e5a9f6adSMax Filippov " bne %0, %1, 1b\n" 134e5a9f6adSMax Filippov : "=&a" (tmp), "=&a" (value) 135e5a9f6adSMax Filippov : "a" (~mask), "a" (p) 136e5a9f6adSMax Filippov : "memory"); 137e5a9f6adSMax Filippov } 138e5a9f6adSMax Filippov 139e5a9f6adSMax Filippov static inline void change_bit(unsigned int bit, volatile unsigned long *p) 140e5a9f6adSMax Filippov { 141e5a9f6adSMax Filippov unsigned long tmp, value; 142e5a9f6adSMax Filippov unsigned long mask = 1UL << (bit & 31); 143e5a9f6adSMax Filippov 144e5a9f6adSMax Filippov p += bit >> 5; 145e5a9f6adSMax Filippov 146e5a9f6adSMax Filippov __asm__ __volatile__( 147e5a9f6adSMax Filippov "1: l32i %1, %3, 0\n" 148e5a9f6adSMax Filippov " wsr %1, scompare1\n" 149e5a9f6adSMax Filippov " xor %0, %1, %2\n" 150e5a9f6adSMax Filippov " s32c1i %0, %3, 0\n" 151e5a9f6adSMax Filippov " bne %0, %1, 1b\n" 152e5a9f6adSMax Filippov : "=&a" (tmp), "=&a" (value) 153e5a9f6adSMax Filippov : "a" (mask), "a" (p) 154e5a9f6adSMax Filippov : "memory"); 155e5a9f6adSMax Filippov } 156e5a9f6adSMax Filippov 157e5a9f6adSMax Filippov static inline int 158e5a9f6adSMax Filippov test_and_set_bit(unsigned int bit, volatile unsigned long *p) 159e5a9f6adSMax Filippov { 160e5a9f6adSMax Filippov unsigned long tmp, value; 161e5a9f6adSMax Filippov unsigned long mask = 1UL << (bit & 31); 162e5a9f6adSMax Filippov 163e5a9f6adSMax Filippov p += bit >> 5; 164e5a9f6adSMax Filippov 165e5a9f6adSMax Filippov __asm__ __volatile__( 166e5a9f6adSMax Filippov "1: l32i %1, %3, 0\n" 167e5a9f6adSMax Filippov " wsr %1, scompare1\n" 168e5a9f6adSMax Filippov " or %0, %1, %2\n" 169e5a9f6adSMax Filippov " s32c1i %0, %3, 0\n" 170e5a9f6adSMax Filippov " bne %0, %1, 1b\n" 171e5a9f6adSMax Filippov : "=&a" (tmp), "=&a" (value) 172e5a9f6adSMax Filippov : "a" (mask), "a" (p) 173e5a9f6adSMax Filippov : "memory"); 174e5a9f6adSMax Filippov 175e5a9f6adSMax Filippov return tmp & mask; 176e5a9f6adSMax Filippov } 177e5a9f6adSMax Filippov 178e5a9f6adSMax Filippov static inline int 179e5a9f6adSMax Filippov test_and_clear_bit(unsigned int bit, volatile unsigned long *p) 180e5a9f6adSMax Filippov { 181e5a9f6adSMax Filippov unsigned long tmp, value; 182e5a9f6adSMax Filippov unsigned long mask = 1UL << (bit & 31); 183e5a9f6adSMax Filippov 184e5a9f6adSMax Filippov p += bit >> 5; 185e5a9f6adSMax Filippov 186e5a9f6adSMax Filippov __asm__ __volatile__( 187e5a9f6adSMax Filippov "1: l32i %1, %3, 0\n" 188e5a9f6adSMax Filippov " wsr %1, scompare1\n" 189e5a9f6adSMax Filippov " and %0, %1, %2\n" 190e5a9f6adSMax Filippov " s32c1i %0, %3, 0\n" 191e5a9f6adSMax Filippov " bne %0, %1, 1b\n" 192e5a9f6adSMax Filippov : "=&a" (tmp), "=&a" (value) 193e5a9f6adSMax Filippov : "a" (~mask), "a" (p) 194e5a9f6adSMax Filippov : "memory"); 195e5a9f6adSMax Filippov 196e5a9f6adSMax Filippov return tmp & mask; 197e5a9f6adSMax Filippov } 198e5a9f6adSMax Filippov 199e5a9f6adSMax Filippov static inline int 200e5a9f6adSMax Filippov test_and_change_bit(unsigned int bit, volatile unsigned long *p) 201e5a9f6adSMax Filippov { 202e5a9f6adSMax Filippov unsigned long tmp, value; 203e5a9f6adSMax Filippov unsigned long mask = 1UL << (bit & 31); 204e5a9f6adSMax Filippov 205e5a9f6adSMax Filippov p += bit >> 5; 206e5a9f6adSMax Filippov 207e5a9f6adSMax Filippov __asm__ __volatile__( 208e5a9f6adSMax Filippov "1: l32i %1, %3, 0\n" 209e5a9f6adSMax Filippov " wsr %1, scompare1\n" 210e5a9f6adSMax Filippov " xor %0, %1, %2\n" 211e5a9f6adSMax Filippov " s32c1i %0, %3, 0\n" 212e5a9f6adSMax Filippov " bne %0, %1, 1b\n" 213e5a9f6adSMax Filippov : "=&a" (tmp), "=&a" (value) 214e5a9f6adSMax Filippov : "a" (mask), "a" (p) 215e5a9f6adSMax Filippov : "memory"); 216e5a9f6adSMax Filippov 217e5a9f6adSMax Filippov return tmp & mask; 218e5a9f6adSMax Filippov } 219e5a9f6adSMax Filippov 220e5a9f6adSMax Filippov #else 221e5a9f6adSMax Filippov 222e5a9f6adSMax Filippov #include <asm-generic/bitops/atomic.h> 223e5a9f6adSMax Filippov 224e5a9f6adSMax Filippov #endif /* XCHAL_HAVE_S32C1I */ 225e5a9f6adSMax Filippov 226367b8112SChris Zankel #include <asm-generic/bitops/find.h> 227861b5ae7SAkinobu Mita #include <asm-generic/bitops/le.h> 228367b8112SChris Zankel 229148817baSAkinobu Mita #include <asm-generic/bitops/ext2-atomic-setbit.h> 230367b8112SChris Zankel 231367b8112SChris Zankel #include <asm-generic/bitops/hweight.h> 232367b8112SChris Zankel #include <asm-generic/bitops/lock.h> 233367b8112SChris Zankel #include <asm-generic/bitops/sched.h> 234367b8112SChris Zankel 235367b8112SChris Zankel #endif /* __KERNEL__ */ 236367b8112SChris Zankel 237367b8112SChris Zankel #endif /* _XTENSA_BITOPS_H */ 238