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 #ifndef _LINUX_BITOPS_H 17367b8112SChris Zankel #error only <linux/bitops.h> can be included directly 18367b8112SChris Zankel #endif 19367b8112SChris Zankel 20367b8112SChris Zankel #include <asm/processor.h> 21367b8112SChris Zankel #include <asm/byteorder.h> 2209a01c0cSPeter Zijlstra #include <asm/barrier.h> 23367b8112SChris Zankel 24367b8112SChris Zankel #include <asm-generic/bitops/non-atomic.h> 25367b8112SChris Zankel 26367b8112SChris Zankel #if XCHAL_HAVE_NSA 27367b8112SChris Zankel 28367b8112SChris Zankel static inline unsigned long __cntlz (unsigned long x) 29367b8112SChris Zankel { 30367b8112SChris Zankel int lz; 31367b8112SChris Zankel asm ("nsau %0, %1" : "=r" (lz) : "r" (x)); 32367b8112SChris Zankel return lz; 33367b8112SChris Zankel } 34367b8112SChris Zankel 35367b8112SChris Zankel /* 36367b8112SChris Zankel * ffz: Find first zero in word. Undefined if no zero exists. 37367b8112SChris Zankel * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). 38367b8112SChris Zankel */ 39367b8112SChris Zankel 40367b8112SChris Zankel static inline int ffz(unsigned long x) 41367b8112SChris Zankel { 42367b8112SChris Zankel return 31 - __cntlz(~x & -~x); 43367b8112SChris Zankel } 44367b8112SChris Zankel 45367b8112SChris Zankel /* 46367b8112SChris Zankel * __ffs: Find first bit set in word. Return 0 for bit 0 47367b8112SChris Zankel */ 48367b8112SChris Zankel 4912c8007dSMax Filippov static inline unsigned long __ffs(unsigned long x) 50367b8112SChris Zankel { 51367b8112SChris Zankel return 31 - __cntlz(x & -x); 52367b8112SChris Zankel } 53367b8112SChris Zankel 54367b8112SChris Zankel /* 55367b8112SChris Zankel * ffs: Find first bit set in word. This is defined the same way as 56367b8112SChris Zankel * the libc and compiler builtin ffs routines, therefore 57367b8112SChris Zankel * differs in spirit from the above ffz (man ffs). 58367b8112SChris Zankel */ 59367b8112SChris Zankel 60367b8112SChris Zankel static inline int ffs(unsigned long x) 61367b8112SChris Zankel { 62367b8112SChris Zankel return 32 - __cntlz(x & -x); 63367b8112SChris Zankel } 64367b8112SChris Zankel 65367b8112SChris Zankel /* 66367b8112SChris Zankel * fls: Find last (most-significant) bit set in word. 67367b8112SChris Zankel * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. 68367b8112SChris Zankel */ 69367b8112SChris Zankel 70367b8112SChris Zankel static inline int fls (unsigned int x) 71367b8112SChris Zankel { 72367b8112SChris Zankel return 32 - __cntlz(x); 73367b8112SChris Zankel } 74367b8112SChris Zankel 7552fefcecSLinus Torvalds /** 7652fefcecSLinus Torvalds * __fls - find last (most-significant) set bit in a long word 7752fefcecSLinus Torvalds * @word: the word to search 7852fefcecSLinus Torvalds * 7952fefcecSLinus Torvalds * Undefined if no set bit exists, so code should check against 0 first. 8052fefcecSLinus Torvalds */ 8152fefcecSLinus Torvalds static inline unsigned long __fls(unsigned long word) 8252fefcecSLinus Torvalds { 8352fefcecSLinus Torvalds return 31 - __cntlz(word); 8452fefcecSLinus Torvalds } 85367b8112SChris Zankel #else 86367b8112SChris Zankel 87367b8112SChris Zankel /* Use the generic implementation if we don't have the nsa/nsau instructions. */ 88367b8112SChris Zankel 89367b8112SChris Zankel # include <asm-generic/bitops/ffs.h> 90367b8112SChris Zankel # include <asm-generic/bitops/__ffs.h> 91367b8112SChris Zankel # include <asm-generic/bitops/ffz.h> 92367b8112SChris Zankel # include <asm-generic/bitops/fls.h> 9352fefcecSLinus Torvalds # include <asm-generic/bitops/__fls.h> 94367b8112SChris Zankel 95367b8112SChris Zankel #endif 96367b8112SChris Zankel 97367b8112SChris Zankel #include <asm-generic/bitops/fls64.h> 98e5a9f6adSMax Filippov 99f7c34874SMax Filippov #if XCHAL_HAVE_EXCLUSIVE 100f7c34874SMax Filippov 101b387dc04SMax Filippov #define BIT_OP(op, insn, inv) \ 102b387dc04SMax Filippov static inline void op##_bit(unsigned int bit, volatile unsigned long *p)\ 103b387dc04SMax Filippov { \ 104b387dc04SMax Filippov unsigned long tmp; \ 105b387dc04SMax Filippov unsigned long mask = 1UL << (bit & 31); \ 106b387dc04SMax Filippov \ 107b387dc04SMax Filippov p += bit >> 5; \ 108b387dc04SMax Filippov \ 109b387dc04SMax Filippov __asm__ __volatile__( \ 110e4449170SMax Filippov "1: l32ex %[tmp], %[addr]\n" \ 111e4449170SMax Filippov " "insn" %[tmp], %[tmp], %[mask]\n" \ 112e4449170SMax Filippov " s32ex %[tmp], %[addr]\n" \ 113e4449170SMax Filippov " getex %[tmp]\n" \ 114e4449170SMax Filippov " beqz %[tmp], 1b\n" \ 115e4449170SMax Filippov : [tmp] "=&a" (tmp) \ 116e4449170SMax Filippov : [mask] "a" (inv mask), [addr] "a" (p) \ 117b387dc04SMax Filippov : "memory"); \ 118f7c34874SMax Filippov } 119f7c34874SMax Filippov 120b387dc04SMax Filippov #define TEST_AND_BIT_OP(op, insn, inv) \ 121b387dc04SMax Filippov static inline int \ 122b387dc04SMax Filippov test_and_##op##_bit(unsigned int bit, volatile unsigned long *p) \ 123b387dc04SMax Filippov { \ 124b387dc04SMax Filippov unsigned long tmp, value; \ 125b387dc04SMax Filippov unsigned long mask = 1UL << (bit & 31); \ 126b387dc04SMax Filippov \ 127b387dc04SMax Filippov p += bit >> 5; \ 128b387dc04SMax Filippov \ 129b387dc04SMax Filippov __asm__ __volatile__( \ 130e4449170SMax Filippov "1: l32ex %[value], %[addr]\n" \ 131e4449170SMax Filippov " "insn" %[tmp], %[value], %[mask]\n" \ 132e4449170SMax Filippov " s32ex %[tmp], %[addr]\n" \ 133e4449170SMax Filippov " getex %[tmp]\n" \ 134e4449170SMax Filippov " beqz %[tmp], 1b\n" \ 135e4449170SMax Filippov : [tmp] "=&a" (tmp), [value] "=&a" (value) \ 136e4449170SMax Filippov : [mask] "a" (inv mask), [addr] "a" (p) \ 137b387dc04SMax Filippov : "memory"); \ 138b387dc04SMax Filippov \ 139b387dc04SMax Filippov return value & mask; \ 140f7c34874SMax Filippov } 141f7c34874SMax Filippov 142f7c34874SMax Filippov #elif XCHAL_HAVE_S32C1I 143e5a9f6adSMax Filippov 144b387dc04SMax Filippov #define BIT_OP(op, insn, inv) \ 145b387dc04SMax Filippov static inline void op##_bit(unsigned int bit, volatile unsigned long *p)\ 146b387dc04SMax Filippov { \ 147b387dc04SMax Filippov unsigned long tmp, value; \ 148b387dc04SMax Filippov unsigned long mask = 1UL << (bit & 31); \ 149b387dc04SMax Filippov \ 150b387dc04SMax Filippov p += bit >> 5; \ 151b387dc04SMax Filippov \ 152b387dc04SMax Filippov __asm__ __volatile__( \ 153e4449170SMax Filippov "1: l32i %[value], %[addr], 0\n" \ 154e4449170SMax Filippov " wsr %[value], scompare1\n" \ 155e4449170SMax Filippov " "insn" %[tmp], %[value], %[mask]\n" \ 156e4449170SMax Filippov " s32c1i %[tmp], %[addr], 0\n" \ 157e4449170SMax Filippov " bne %[tmp], %[value], 1b\n" \ 158e4449170SMax Filippov : [tmp] "=&a" (tmp), [value] "=&a" (value) \ 159e4449170SMax Filippov : [mask] "a" (inv mask), [addr] "a" (p) \ 160b387dc04SMax Filippov : "memory"); \ 161e5a9f6adSMax Filippov } 162e5a9f6adSMax Filippov 163b387dc04SMax Filippov #define TEST_AND_BIT_OP(op, insn, inv) \ 164b387dc04SMax Filippov static inline int \ 165b387dc04SMax Filippov test_and_##op##_bit(unsigned int bit, volatile unsigned long *p) \ 166b387dc04SMax Filippov { \ 167b387dc04SMax Filippov unsigned long tmp, value; \ 168b387dc04SMax Filippov unsigned long mask = 1UL << (bit & 31); \ 169b387dc04SMax Filippov \ 170b387dc04SMax Filippov p += bit >> 5; \ 171b387dc04SMax Filippov \ 172b387dc04SMax Filippov __asm__ __volatile__( \ 173e4449170SMax Filippov "1: l32i %[value], %[addr], 0\n" \ 174e4449170SMax Filippov " wsr %[value], scompare1\n" \ 175e4449170SMax Filippov " "insn" %[tmp], %[value], %[mask]\n" \ 176e4449170SMax Filippov " s32c1i %[tmp], %[addr], 0\n" \ 177e4449170SMax Filippov " bne %[tmp], %[value], 1b\n" \ 178e4449170SMax Filippov : [tmp] "=&a" (tmp), [value] "=&a" (value) \ 179e4449170SMax Filippov : [mask] "a" (inv mask), [addr] "a" (p) \ 180b387dc04SMax Filippov : "memory"); \ 181b387dc04SMax Filippov \ 182b387dc04SMax Filippov return tmp & mask; \ 183e5a9f6adSMax Filippov } 184e5a9f6adSMax Filippov 185e5a9f6adSMax Filippov #else 186e5a9f6adSMax Filippov 187b387dc04SMax Filippov #define BIT_OP(op, insn, inv) 188b387dc04SMax Filippov #define TEST_AND_BIT_OP(op, insn, inv) 189b387dc04SMax Filippov 190e5a9f6adSMax Filippov #include <asm-generic/bitops/atomic.h> 191e5a9f6adSMax Filippov 192e5a9f6adSMax Filippov #endif /* XCHAL_HAVE_S32C1I */ 193e5a9f6adSMax Filippov 194b387dc04SMax Filippov #define BIT_OPS(op, insn, inv) \ 195b387dc04SMax Filippov BIT_OP(op, insn, inv) \ 196b387dc04SMax Filippov TEST_AND_BIT_OP(op, insn, inv) 197b387dc04SMax Filippov 198b387dc04SMax Filippov BIT_OPS(set, "or", ) 199b387dc04SMax Filippov BIT_OPS(clear, "and", ~) 200b387dc04SMax Filippov BIT_OPS(change, "xor", ) 201b387dc04SMax Filippov 202b387dc04SMax Filippov #undef BIT_OPS 203b387dc04SMax Filippov #undef BIT_OP 204b387dc04SMax Filippov #undef TEST_AND_BIT_OP 205b387dc04SMax Filippov 206367b8112SChris Zankel #include <asm-generic/bitops/find.h> 207861b5ae7SAkinobu Mita #include <asm-generic/bitops/le.h> 208367b8112SChris Zankel 209148817baSAkinobu Mita #include <asm-generic/bitops/ext2-atomic-setbit.h> 210367b8112SChris Zankel 211367b8112SChris Zankel #include <asm-generic/bitops/hweight.h> 212367b8112SChris Zankel #include <asm-generic/bitops/lock.h> 213367b8112SChris Zankel #include <asm-generic/bitops/sched.h> 214367b8112SChris Zankel 215367b8112SChris Zankel #endif /* _XTENSA_BITOPS_H */ 216