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> 24367b8112SChris Zankel 25367b8112SChris Zankel #ifdef CONFIG_SMP 26367b8112SChris Zankel # error SMP not supported on this architecture 27367b8112SChris Zankel #endif 28367b8112SChris Zankel 29367b8112SChris Zankel #define smp_mb__before_clear_bit() barrier() 30367b8112SChris Zankel #define smp_mb__after_clear_bit() barrier() 31367b8112SChris Zankel 32367b8112SChris Zankel #include <asm-generic/bitops/non-atomic.h> 33367b8112SChris Zankel 34367b8112SChris Zankel #if XCHAL_HAVE_NSA 35367b8112SChris Zankel 36367b8112SChris Zankel static inline unsigned long __cntlz (unsigned long x) 37367b8112SChris Zankel { 38367b8112SChris Zankel int lz; 39367b8112SChris Zankel asm ("nsau %0, %1" : "=r" (lz) : "r" (x)); 40367b8112SChris Zankel return lz; 41367b8112SChris Zankel } 42367b8112SChris Zankel 43367b8112SChris Zankel /* 44367b8112SChris Zankel * ffz: Find first zero in word. Undefined if no zero exists. 45367b8112SChris Zankel * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). 46367b8112SChris Zankel */ 47367b8112SChris Zankel 48367b8112SChris Zankel static inline int ffz(unsigned long x) 49367b8112SChris Zankel { 50367b8112SChris Zankel return 31 - __cntlz(~x & -~x); 51367b8112SChris Zankel } 52367b8112SChris Zankel 53367b8112SChris Zankel /* 54367b8112SChris Zankel * __ffs: Find first bit set in word. Return 0 for bit 0 55367b8112SChris Zankel */ 56367b8112SChris Zankel 57367b8112SChris Zankel static inline int __ffs(unsigned long x) 58367b8112SChris Zankel { 59367b8112SChris Zankel return 31 - __cntlz(x & -x); 60367b8112SChris Zankel } 61367b8112SChris Zankel 62367b8112SChris Zankel /* 63367b8112SChris Zankel * ffs: Find first bit set in word. This is defined the same way as 64367b8112SChris Zankel * the libc and compiler builtin ffs routines, therefore 65367b8112SChris Zankel * differs in spirit from the above ffz (man ffs). 66367b8112SChris Zankel */ 67367b8112SChris Zankel 68367b8112SChris Zankel static inline int ffs(unsigned long x) 69367b8112SChris Zankel { 70367b8112SChris Zankel return 32 - __cntlz(x & -x); 71367b8112SChris Zankel } 72367b8112SChris Zankel 73367b8112SChris Zankel /* 74367b8112SChris Zankel * fls: Find last (most-significant) bit set in word. 75367b8112SChris Zankel * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. 76367b8112SChris Zankel */ 77367b8112SChris Zankel 78367b8112SChris Zankel static inline int fls (unsigned int x) 79367b8112SChris Zankel { 80367b8112SChris Zankel return 32 - __cntlz(x); 81367b8112SChris Zankel } 82367b8112SChris Zankel 8352fefcecSLinus Torvalds /** 8452fefcecSLinus Torvalds * __fls - find last (most-significant) set bit in a long word 8552fefcecSLinus Torvalds * @word: the word to search 8652fefcecSLinus Torvalds * 8752fefcecSLinus Torvalds * Undefined if no set bit exists, so code should check against 0 first. 8852fefcecSLinus Torvalds */ 8952fefcecSLinus Torvalds static inline unsigned long __fls(unsigned long word) 9052fefcecSLinus Torvalds { 9152fefcecSLinus Torvalds return 31 - __cntlz(word); 9252fefcecSLinus Torvalds } 93367b8112SChris Zankel #else 94367b8112SChris Zankel 95367b8112SChris Zankel /* Use the generic implementation if we don't have the nsa/nsau instructions. */ 96367b8112SChris Zankel 97367b8112SChris Zankel # include <asm-generic/bitops/ffs.h> 98367b8112SChris Zankel # include <asm-generic/bitops/__ffs.h> 99367b8112SChris Zankel # include <asm-generic/bitops/ffz.h> 100367b8112SChris Zankel # include <asm-generic/bitops/fls.h> 10152fefcecSLinus Torvalds # include <asm-generic/bitops/__fls.h> 102367b8112SChris Zankel 103367b8112SChris Zankel #endif 104367b8112SChris Zankel 105367b8112SChris Zankel #include <asm-generic/bitops/fls64.h> 106*e5a9f6adSMax Filippov 107*e5a9f6adSMax Filippov #if XCHAL_HAVE_S32C1I 108*e5a9f6adSMax Filippov 109*e5a9f6adSMax Filippov static inline void set_bit(unsigned int bit, volatile unsigned long *p) 110*e5a9f6adSMax Filippov { 111*e5a9f6adSMax Filippov unsigned long tmp, value; 112*e5a9f6adSMax Filippov unsigned long mask = 1UL << (bit & 31); 113*e5a9f6adSMax Filippov 114*e5a9f6adSMax Filippov p += bit >> 5; 115*e5a9f6adSMax Filippov 116*e5a9f6adSMax Filippov __asm__ __volatile__( 117*e5a9f6adSMax Filippov "1: l32i %1, %3, 0\n" 118*e5a9f6adSMax Filippov " wsr %1, scompare1\n" 119*e5a9f6adSMax Filippov " or %0, %1, %2\n" 120*e5a9f6adSMax Filippov " s32c1i %0, %3, 0\n" 121*e5a9f6adSMax Filippov " bne %0, %1, 1b\n" 122*e5a9f6adSMax Filippov : "=&a" (tmp), "=&a" (value) 123*e5a9f6adSMax Filippov : "a" (mask), "a" (p) 124*e5a9f6adSMax Filippov : "memory"); 125*e5a9f6adSMax Filippov } 126*e5a9f6adSMax Filippov 127*e5a9f6adSMax Filippov static inline void clear_bit(unsigned int bit, volatile unsigned long *p) 128*e5a9f6adSMax Filippov { 129*e5a9f6adSMax Filippov unsigned long tmp, value; 130*e5a9f6adSMax Filippov unsigned long mask = 1UL << (bit & 31); 131*e5a9f6adSMax Filippov 132*e5a9f6adSMax Filippov p += bit >> 5; 133*e5a9f6adSMax Filippov 134*e5a9f6adSMax Filippov __asm__ __volatile__( 135*e5a9f6adSMax Filippov "1: l32i %1, %3, 0\n" 136*e5a9f6adSMax Filippov " wsr %1, scompare1\n" 137*e5a9f6adSMax Filippov " and %0, %1, %2\n" 138*e5a9f6adSMax Filippov " s32c1i %0, %3, 0\n" 139*e5a9f6adSMax Filippov " bne %0, %1, 1b\n" 140*e5a9f6adSMax Filippov : "=&a" (tmp), "=&a" (value) 141*e5a9f6adSMax Filippov : "a" (~mask), "a" (p) 142*e5a9f6adSMax Filippov : "memory"); 143*e5a9f6adSMax Filippov } 144*e5a9f6adSMax Filippov 145*e5a9f6adSMax Filippov static inline void change_bit(unsigned int bit, volatile unsigned long *p) 146*e5a9f6adSMax Filippov { 147*e5a9f6adSMax Filippov unsigned long tmp, value; 148*e5a9f6adSMax Filippov unsigned long mask = 1UL << (bit & 31); 149*e5a9f6adSMax Filippov 150*e5a9f6adSMax Filippov p += bit >> 5; 151*e5a9f6adSMax Filippov 152*e5a9f6adSMax Filippov __asm__ __volatile__( 153*e5a9f6adSMax Filippov "1: l32i %1, %3, 0\n" 154*e5a9f6adSMax Filippov " wsr %1, scompare1\n" 155*e5a9f6adSMax Filippov " xor %0, %1, %2\n" 156*e5a9f6adSMax Filippov " s32c1i %0, %3, 0\n" 157*e5a9f6adSMax Filippov " bne %0, %1, 1b\n" 158*e5a9f6adSMax Filippov : "=&a" (tmp), "=&a" (value) 159*e5a9f6adSMax Filippov : "a" (mask), "a" (p) 160*e5a9f6adSMax Filippov : "memory"); 161*e5a9f6adSMax Filippov } 162*e5a9f6adSMax Filippov 163*e5a9f6adSMax Filippov static inline int 164*e5a9f6adSMax Filippov test_and_set_bit(unsigned int bit, volatile unsigned long *p) 165*e5a9f6adSMax Filippov { 166*e5a9f6adSMax Filippov unsigned long tmp, value; 167*e5a9f6adSMax Filippov unsigned long mask = 1UL << (bit & 31); 168*e5a9f6adSMax Filippov 169*e5a9f6adSMax Filippov p += bit >> 5; 170*e5a9f6adSMax Filippov 171*e5a9f6adSMax Filippov __asm__ __volatile__( 172*e5a9f6adSMax Filippov "1: l32i %1, %3, 0\n" 173*e5a9f6adSMax Filippov " wsr %1, scompare1\n" 174*e5a9f6adSMax Filippov " or %0, %1, %2\n" 175*e5a9f6adSMax Filippov " s32c1i %0, %3, 0\n" 176*e5a9f6adSMax Filippov " bne %0, %1, 1b\n" 177*e5a9f6adSMax Filippov : "=&a" (tmp), "=&a" (value) 178*e5a9f6adSMax Filippov : "a" (mask), "a" (p) 179*e5a9f6adSMax Filippov : "memory"); 180*e5a9f6adSMax Filippov 181*e5a9f6adSMax Filippov return tmp & mask; 182*e5a9f6adSMax Filippov } 183*e5a9f6adSMax Filippov 184*e5a9f6adSMax Filippov static inline int 185*e5a9f6adSMax Filippov test_and_clear_bit(unsigned int bit, volatile unsigned long *p) 186*e5a9f6adSMax Filippov { 187*e5a9f6adSMax Filippov unsigned long tmp, value; 188*e5a9f6adSMax Filippov unsigned long mask = 1UL << (bit & 31); 189*e5a9f6adSMax Filippov 190*e5a9f6adSMax Filippov p += bit >> 5; 191*e5a9f6adSMax Filippov 192*e5a9f6adSMax Filippov __asm__ __volatile__( 193*e5a9f6adSMax Filippov "1: l32i %1, %3, 0\n" 194*e5a9f6adSMax Filippov " wsr %1, scompare1\n" 195*e5a9f6adSMax Filippov " and %0, %1, %2\n" 196*e5a9f6adSMax Filippov " s32c1i %0, %3, 0\n" 197*e5a9f6adSMax Filippov " bne %0, %1, 1b\n" 198*e5a9f6adSMax Filippov : "=&a" (tmp), "=&a" (value) 199*e5a9f6adSMax Filippov : "a" (~mask), "a" (p) 200*e5a9f6adSMax Filippov : "memory"); 201*e5a9f6adSMax Filippov 202*e5a9f6adSMax Filippov return tmp & mask; 203*e5a9f6adSMax Filippov } 204*e5a9f6adSMax Filippov 205*e5a9f6adSMax Filippov static inline int 206*e5a9f6adSMax Filippov test_and_change_bit(unsigned int bit, volatile unsigned long *p) 207*e5a9f6adSMax Filippov { 208*e5a9f6adSMax Filippov unsigned long tmp, value; 209*e5a9f6adSMax Filippov unsigned long mask = 1UL << (bit & 31); 210*e5a9f6adSMax Filippov 211*e5a9f6adSMax Filippov p += bit >> 5; 212*e5a9f6adSMax Filippov 213*e5a9f6adSMax Filippov __asm__ __volatile__( 214*e5a9f6adSMax Filippov "1: l32i %1, %3, 0\n" 215*e5a9f6adSMax Filippov " wsr %1, scompare1\n" 216*e5a9f6adSMax Filippov " xor %0, %1, %2\n" 217*e5a9f6adSMax Filippov " s32c1i %0, %3, 0\n" 218*e5a9f6adSMax Filippov " bne %0, %1, 1b\n" 219*e5a9f6adSMax Filippov : "=&a" (tmp), "=&a" (value) 220*e5a9f6adSMax Filippov : "a" (mask), "a" (p) 221*e5a9f6adSMax Filippov : "memory"); 222*e5a9f6adSMax Filippov 223*e5a9f6adSMax Filippov return tmp & mask; 224*e5a9f6adSMax Filippov } 225*e5a9f6adSMax Filippov 226*e5a9f6adSMax Filippov #else 227*e5a9f6adSMax Filippov 228*e5a9f6adSMax Filippov #include <asm-generic/bitops/atomic.h> 229*e5a9f6adSMax Filippov 230*e5a9f6adSMax Filippov #endif /* XCHAL_HAVE_S32C1I */ 231*e5a9f6adSMax Filippov 232367b8112SChris Zankel #include <asm-generic/bitops/find.h> 233861b5ae7SAkinobu Mita #include <asm-generic/bitops/le.h> 234367b8112SChris Zankel 235148817baSAkinobu Mita #include <asm-generic/bitops/ext2-atomic-setbit.h> 236367b8112SChris Zankel 237367b8112SChris Zankel #include <asm-generic/bitops/hweight.h> 238367b8112SChris Zankel #include <asm-generic/bitops/lock.h> 239367b8112SChris Zankel #include <asm-generic/bitops/sched.h> 240367b8112SChris Zankel 241367b8112SChris Zankel #endif /* __KERNEL__ */ 242367b8112SChris Zankel 243367b8112SChris Zankel #endif /* _XTENSA_BITOPS_H */ 244