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 101*b387dc04SMax Filippov #define BIT_OP(op, insn, inv) \ 102*b387dc04SMax Filippov static inline void op##_bit(unsigned int bit, volatile unsigned long *p)\ 103*b387dc04SMax Filippov { \ 104*b387dc04SMax Filippov unsigned long tmp; \ 105*b387dc04SMax Filippov unsigned long mask = 1UL << (bit & 31); \ 106*b387dc04SMax Filippov \ 107*b387dc04SMax Filippov p += bit >> 5; \ 108*b387dc04SMax Filippov \ 109*b387dc04SMax Filippov __asm__ __volatile__( \ 110*b387dc04SMax Filippov "1: l32ex %0, %2\n" \ 111*b387dc04SMax Filippov " "insn" %0, %0, %1\n" \ 112*b387dc04SMax Filippov " s32ex %0, %2\n" \ 113*b387dc04SMax Filippov " getex %0\n" \ 114*b387dc04SMax Filippov " beqz %0, 1b\n" \ 115*b387dc04SMax Filippov : "=&a" (tmp) \ 116*b387dc04SMax Filippov : "a" (inv mask), "a" (p) \ 117*b387dc04SMax Filippov : "memory"); \ 118f7c34874SMax Filippov } 119f7c34874SMax Filippov 120*b387dc04SMax Filippov #define TEST_AND_BIT_OP(op, insn, inv) \ 121*b387dc04SMax Filippov static inline int \ 122*b387dc04SMax Filippov test_and_##op##_bit(unsigned int bit, volatile unsigned long *p) \ 123*b387dc04SMax Filippov { \ 124*b387dc04SMax Filippov unsigned long tmp, value; \ 125*b387dc04SMax Filippov unsigned long mask = 1UL << (bit & 31); \ 126*b387dc04SMax Filippov \ 127*b387dc04SMax Filippov p += bit >> 5; \ 128*b387dc04SMax Filippov \ 129*b387dc04SMax Filippov __asm__ __volatile__( \ 130*b387dc04SMax Filippov "1: l32ex %1, %3\n" \ 131*b387dc04SMax Filippov " "insn" %0, %1, %2\n" \ 132*b387dc04SMax Filippov " s32ex %0, %3\n" \ 133*b387dc04SMax Filippov " getex %0\n" \ 134*b387dc04SMax Filippov " beqz %0, 1b\n" \ 135*b387dc04SMax Filippov : "=&a" (tmp), "=&a" (value) \ 136*b387dc04SMax Filippov : "a" (inv mask), "a" (p) \ 137*b387dc04SMax Filippov : "memory"); \ 138*b387dc04SMax Filippov \ 139*b387dc04SMax Filippov return value & mask; \ 140f7c34874SMax Filippov } 141f7c34874SMax Filippov 142f7c34874SMax Filippov #elif XCHAL_HAVE_S32C1I 143e5a9f6adSMax Filippov 144*b387dc04SMax Filippov #define BIT_OP(op, insn, inv) \ 145*b387dc04SMax Filippov static inline void op##_bit(unsigned int bit, volatile unsigned long *p)\ 146*b387dc04SMax Filippov { \ 147*b387dc04SMax Filippov unsigned long tmp, value; \ 148*b387dc04SMax Filippov unsigned long mask = 1UL << (bit & 31); \ 149*b387dc04SMax Filippov \ 150*b387dc04SMax Filippov p += bit >> 5; \ 151*b387dc04SMax Filippov \ 152*b387dc04SMax Filippov __asm__ __volatile__( \ 153*b387dc04SMax Filippov "1: l32i %1, %3, 0\n" \ 154*b387dc04SMax Filippov " wsr %1, scompare1\n" \ 155*b387dc04SMax Filippov " "insn" %0, %1, %2\n" \ 156*b387dc04SMax Filippov " s32c1i %0, %3, 0\n" \ 157*b387dc04SMax Filippov " bne %0, %1, 1b\n" \ 158*b387dc04SMax Filippov : "=&a" (tmp), "=&a" (value) \ 159*b387dc04SMax Filippov : "a" (inv mask), "a" (p) \ 160*b387dc04SMax Filippov : "memory"); \ 161e5a9f6adSMax Filippov } 162e5a9f6adSMax Filippov 163*b387dc04SMax Filippov #define TEST_AND_BIT_OP(op, insn, inv) \ 164*b387dc04SMax Filippov static inline int \ 165*b387dc04SMax Filippov test_and_##op##_bit(unsigned int bit, volatile unsigned long *p) \ 166*b387dc04SMax Filippov { \ 167*b387dc04SMax Filippov unsigned long tmp, value; \ 168*b387dc04SMax Filippov unsigned long mask = 1UL << (bit & 31); \ 169*b387dc04SMax Filippov \ 170*b387dc04SMax Filippov p += bit >> 5; \ 171*b387dc04SMax Filippov \ 172*b387dc04SMax Filippov __asm__ __volatile__( \ 173*b387dc04SMax Filippov "1: l32i %1, %3, 0\n" \ 174*b387dc04SMax Filippov " wsr %1, scompare1\n" \ 175*b387dc04SMax Filippov " "insn" %0, %1, %2\n" \ 176*b387dc04SMax Filippov " s32c1i %0, %3, 0\n" \ 177*b387dc04SMax Filippov " bne %0, %1, 1b\n" \ 178*b387dc04SMax Filippov : "=&a" (tmp), "=&a" (value) \ 179*b387dc04SMax Filippov : "a" (inv mask), "a" (p) \ 180*b387dc04SMax Filippov : "memory"); \ 181*b387dc04SMax Filippov \ 182*b387dc04SMax Filippov return tmp & mask; \ 183e5a9f6adSMax Filippov } 184e5a9f6adSMax Filippov 185e5a9f6adSMax Filippov #else 186e5a9f6adSMax Filippov 187*b387dc04SMax Filippov #define BIT_OP(op, insn, inv) 188*b387dc04SMax Filippov #define TEST_AND_BIT_OP(op, insn, inv) 189*b387dc04SMax Filippov 190e5a9f6adSMax Filippov #include <asm-generic/bitops/atomic.h> 191e5a9f6adSMax Filippov 192e5a9f6adSMax Filippov #endif /* XCHAL_HAVE_S32C1I */ 193e5a9f6adSMax Filippov 194*b387dc04SMax Filippov #define BIT_OPS(op, insn, inv) \ 195*b387dc04SMax Filippov BIT_OP(op, insn, inv) \ 196*b387dc04SMax Filippov TEST_AND_BIT_OP(op, insn, inv) 197*b387dc04SMax Filippov 198*b387dc04SMax Filippov BIT_OPS(set, "or", ) 199*b387dc04SMax Filippov BIT_OPS(clear, "and", ~) 200*b387dc04SMax Filippov BIT_OPS(change, "xor", ) 201*b387dc04SMax Filippov 202*b387dc04SMax Filippov #undef BIT_OPS 203*b387dc04SMax Filippov #undef BIT_OP 204*b387dc04SMax Filippov #undef TEST_AND_BIT_OP 205*b387dc04SMax 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