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 99*f7c34874SMax Filippov #if XCHAL_HAVE_EXCLUSIVE 100*f7c34874SMax Filippov 101*f7c34874SMax Filippov static inline void set_bit(unsigned int bit, volatile unsigned long *p) 102*f7c34874SMax Filippov { 103*f7c34874SMax Filippov unsigned long tmp; 104*f7c34874SMax Filippov unsigned long mask = 1UL << (bit & 31); 105*f7c34874SMax Filippov 106*f7c34874SMax Filippov p += bit >> 5; 107*f7c34874SMax Filippov 108*f7c34874SMax Filippov __asm__ __volatile__( 109*f7c34874SMax Filippov "1: l32ex %0, %2\n" 110*f7c34874SMax Filippov " or %0, %0, %1\n" 111*f7c34874SMax Filippov " s32ex %0, %2\n" 112*f7c34874SMax Filippov " getex %0\n" 113*f7c34874SMax Filippov " beqz %0, 1b\n" 114*f7c34874SMax Filippov : "=&a" (tmp) 115*f7c34874SMax Filippov : "a" (mask), "a" (p) 116*f7c34874SMax Filippov : "memory"); 117*f7c34874SMax Filippov } 118*f7c34874SMax Filippov 119*f7c34874SMax Filippov static inline void clear_bit(unsigned int bit, volatile unsigned long *p) 120*f7c34874SMax Filippov { 121*f7c34874SMax Filippov unsigned long tmp; 122*f7c34874SMax Filippov unsigned long mask = 1UL << (bit & 31); 123*f7c34874SMax Filippov 124*f7c34874SMax Filippov p += bit >> 5; 125*f7c34874SMax Filippov 126*f7c34874SMax Filippov __asm__ __volatile__( 127*f7c34874SMax Filippov "1: l32ex %0, %2\n" 128*f7c34874SMax Filippov " and %0, %0, %1\n" 129*f7c34874SMax Filippov " s32ex %0, %2\n" 130*f7c34874SMax Filippov " getex %0\n" 131*f7c34874SMax Filippov " beqz %0, 1b\n" 132*f7c34874SMax Filippov : "=&a" (tmp) 133*f7c34874SMax Filippov : "a" (~mask), "a" (p) 134*f7c34874SMax Filippov : "memory"); 135*f7c34874SMax Filippov } 136*f7c34874SMax Filippov 137*f7c34874SMax Filippov static inline void change_bit(unsigned int bit, volatile unsigned long *p) 138*f7c34874SMax Filippov { 139*f7c34874SMax Filippov unsigned long tmp; 140*f7c34874SMax Filippov unsigned long mask = 1UL << (bit & 31); 141*f7c34874SMax Filippov 142*f7c34874SMax Filippov p += bit >> 5; 143*f7c34874SMax Filippov 144*f7c34874SMax Filippov __asm__ __volatile__( 145*f7c34874SMax Filippov "1: l32ex %0, %2\n" 146*f7c34874SMax Filippov " xor %0, %0, %1\n" 147*f7c34874SMax Filippov " s32ex %0, %2\n" 148*f7c34874SMax Filippov " getex %0\n" 149*f7c34874SMax Filippov " beqz %0, 1b\n" 150*f7c34874SMax Filippov : "=&a" (tmp) 151*f7c34874SMax Filippov : "a" (~mask), "a" (p) 152*f7c34874SMax Filippov : "memory"); 153*f7c34874SMax Filippov } 154*f7c34874SMax Filippov 155*f7c34874SMax Filippov static inline int 156*f7c34874SMax Filippov test_and_set_bit(unsigned int bit, volatile unsigned long *p) 157*f7c34874SMax Filippov { 158*f7c34874SMax Filippov unsigned long tmp, value; 159*f7c34874SMax Filippov unsigned long mask = 1UL << (bit & 31); 160*f7c34874SMax Filippov 161*f7c34874SMax Filippov p += bit >> 5; 162*f7c34874SMax Filippov 163*f7c34874SMax Filippov __asm__ __volatile__( 164*f7c34874SMax Filippov "1: l32ex %1, %3\n" 165*f7c34874SMax Filippov " or %0, %1, %2\n" 166*f7c34874SMax Filippov " s32ex %0, %3\n" 167*f7c34874SMax Filippov " getex %0\n" 168*f7c34874SMax Filippov " beqz %0, 1b\n" 169*f7c34874SMax Filippov : "=&a" (tmp), "=&a" (value) 170*f7c34874SMax Filippov : "a" (mask), "a" (p) 171*f7c34874SMax Filippov : "memory"); 172*f7c34874SMax Filippov 173*f7c34874SMax Filippov return value & mask; 174*f7c34874SMax Filippov } 175*f7c34874SMax Filippov 176*f7c34874SMax Filippov static inline int 177*f7c34874SMax Filippov test_and_clear_bit(unsigned int bit, volatile unsigned long *p) 178*f7c34874SMax Filippov { 179*f7c34874SMax Filippov unsigned long tmp, value; 180*f7c34874SMax Filippov unsigned long mask = 1UL << (bit & 31); 181*f7c34874SMax Filippov 182*f7c34874SMax Filippov p += bit >> 5; 183*f7c34874SMax Filippov 184*f7c34874SMax Filippov __asm__ __volatile__( 185*f7c34874SMax Filippov "1: l32ex %1, %3\n" 186*f7c34874SMax Filippov " and %0, %1, %2\n" 187*f7c34874SMax Filippov " s32ex %0, %3\n" 188*f7c34874SMax Filippov " getex %0\n" 189*f7c34874SMax Filippov " beqz %0, 1b\n" 190*f7c34874SMax Filippov : "=&a" (tmp), "=&a" (value) 191*f7c34874SMax Filippov : "a" (~mask), "a" (p) 192*f7c34874SMax Filippov : "memory"); 193*f7c34874SMax Filippov 194*f7c34874SMax Filippov return value & mask; 195*f7c34874SMax Filippov } 196*f7c34874SMax Filippov 197*f7c34874SMax Filippov static inline int 198*f7c34874SMax Filippov test_and_change_bit(unsigned int bit, volatile unsigned long *p) 199*f7c34874SMax Filippov { 200*f7c34874SMax Filippov unsigned long tmp, value; 201*f7c34874SMax Filippov unsigned long mask = 1UL << (bit & 31); 202*f7c34874SMax Filippov 203*f7c34874SMax Filippov p += bit >> 5; 204*f7c34874SMax Filippov 205*f7c34874SMax Filippov __asm__ __volatile__( 206*f7c34874SMax Filippov "1: l32ex %1, %3\n" 207*f7c34874SMax Filippov " xor %0, %1, %2\n" 208*f7c34874SMax Filippov " s32ex %0, %3\n" 209*f7c34874SMax Filippov " getex %0\n" 210*f7c34874SMax Filippov " beqz %0, 1b\n" 211*f7c34874SMax Filippov : "=&a" (tmp), "=&a" (value) 212*f7c34874SMax Filippov : "a" (mask), "a" (p) 213*f7c34874SMax Filippov : "memory"); 214*f7c34874SMax Filippov 215*f7c34874SMax Filippov return value & mask; 216*f7c34874SMax Filippov } 217*f7c34874SMax Filippov 218*f7c34874SMax Filippov #elif XCHAL_HAVE_S32C1I 219e5a9f6adSMax Filippov 220e5a9f6adSMax Filippov static inline void set_bit(unsigned int bit, volatile unsigned long *p) 221e5a9f6adSMax Filippov { 222e5a9f6adSMax Filippov unsigned long tmp, value; 223e5a9f6adSMax Filippov unsigned long mask = 1UL << (bit & 31); 224e5a9f6adSMax Filippov 225e5a9f6adSMax Filippov p += bit >> 5; 226e5a9f6adSMax Filippov 227e5a9f6adSMax Filippov __asm__ __volatile__( 228e5a9f6adSMax Filippov "1: l32i %1, %3, 0\n" 229e5a9f6adSMax Filippov " wsr %1, scompare1\n" 230e5a9f6adSMax Filippov " or %0, %1, %2\n" 231e5a9f6adSMax Filippov " s32c1i %0, %3, 0\n" 232e5a9f6adSMax Filippov " bne %0, %1, 1b\n" 233e5a9f6adSMax Filippov : "=&a" (tmp), "=&a" (value) 234e5a9f6adSMax Filippov : "a" (mask), "a" (p) 235e5a9f6adSMax Filippov : "memory"); 236e5a9f6adSMax Filippov } 237e5a9f6adSMax Filippov 238e5a9f6adSMax Filippov static inline void clear_bit(unsigned int bit, volatile unsigned long *p) 239e5a9f6adSMax Filippov { 240e5a9f6adSMax Filippov unsigned long tmp, value; 241e5a9f6adSMax Filippov unsigned long mask = 1UL << (bit & 31); 242e5a9f6adSMax Filippov 243e5a9f6adSMax Filippov p += bit >> 5; 244e5a9f6adSMax Filippov 245e5a9f6adSMax Filippov __asm__ __volatile__( 246e5a9f6adSMax Filippov "1: l32i %1, %3, 0\n" 247e5a9f6adSMax Filippov " wsr %1, scompare1\n" 248e5a9f6adSMax Filippov " and %0, %1, %2\n" 249e5a9f6adSMax Filippov " s32c1i %0, %3, 0\n" 250e5a9f6adSMax Filippov " bne %0, %1, 1b\n" 251e5a9f6adSMax Filippov : "=&a" (tmp), "=&a" (value) 252e5a9f6adSMax Filippov : "a" (~mask), "a" (p) 253e5a9f6adSMax Filippov : "memory"); 254e5a9f6adSMax Filippov } 255e5a9f6adSMax Filippov 256e5a9f6adSMax Filippov static inline void change_bit(unsigned int bit, volatile unsigned long *p) 257e5a9f6adSMax Filippov { 258e5a9f6adSMax Filippov unsigned long tmp, value; 259e5a9f6adSMax Filippov unsigned long mask = 1UL << (bit & 31); 260e5a9f6adSMax Filippov 261e5a9f6adSMax Filippov p += bit >> 5; 262e5a9f6adSMax Filippov 263e5a9f6adSMax Filippov __asm__ __volatile__( 264e5a9f6adSMax Filippov "1: l32i %1, %3, 0\n" 265e5a9f6adSMax Filippov " wsr %1, scompare1\n" 266e5a9f6adSMax Filippov " xor %0, %1, %2\n" 267e5a9f6adSMax Filippov " s32c1i %0, %3, 0\n" 268e5a9f6adSMax Filippov " bne %0, %1, 1b\n" 269e5a9f6adSMax Filippov : "=&a" (tmp), "=&a" (value) 270e5a9f6adSMax Filippov : "a" (mask), "a" (p) 271e5a9f6adSMax Filippov : "memory"); 272e5a9f6adSMax Filippov } 273e5a9f6adSMax Filippov 274e5a9f6adSMax Filippov static inline int 275e5a9f6adSMax Filippov test_and_set_bit(unsigned int bit, volatile unsigned long *p) 276e5a9f6adSMax Filippov { 277e5a9f6adSMax Filippov unsigned long tmp, value; 278e5a9f6adSMax Filippov unsigned long mask = 1UL << (bit & 31); 279e5a9f6adSMax Filippov 280e5a9f6adSMax Filippov p += bit >> 5; 281e5a9f6adSMax Filippov 282e5a9f6adSMax Filippov __asm__ __volatile__( 283e5a9f6adSMax Filippov "1: l32i %1, %3, 0\n" 284e5a9f6adSMax Filippov " wsr %1, scompare1\n" 285e5a9f6adSMax Filippov " or %0, %1, %2\n" 286e5a9f6adSMax Filippov " s32c1i %0, %3, 0\n" 287e5a9f6adSMax Filippov " bne %0, %1, 1b\n" 288e5a9f6adSMax Filippov : "=&a" (tmp), "=&a" (value) 289e5a9f6adSMax Filippov : "a" (mask), "a" (p) 290e5a9f6adSMax Filippov : "memory"); 291e5a9f6adSMax Filippov 292e5a9f6adSMax Filippov return tmp & mask; 293e5a9f6adSMax Filippov } 294e5a9f6adSMax Filippov 295e5a9f6adSMax Filippov static inline int 296e5a9f6adSMax Filippov test_and_clear_bit(unsigned int bit, volatile unsigned long *p) 297e5a9f6adSMax Filippov { 298e5a9f6adSMax Filippov unsigned long tmp, value; 299e5a9f6adSMax Filippov unsigned long mask = 1UL << (bit & 31); 300e5a9f6adSMax Filippov 301e5a9f6adSMax Filippov p += bit >> 5; 302e5a9f6adSMax Filippov 303e5a9f6adSMax Filippov __asm__ __volatile__( 304e5a9f6adSMax Filippov "1: l32i %1, %3, 0\n" 305e5a9f6adSMax Filippov " wsr %1, scompare1\n" 306e5a9f6adSMax Filippov " and %0, %1, %2\n" 307e5a9f6adSMax Filippov " s32c1i %0, %3, 0\n" 308e5a9f6adSMax Filippov " bne %0, %1, 1b\n" 309e5a9f6adSMax Filippov : "=&a" (tmp), "=&a" (value) 310e5a9f6adSMax Filippov : "a" (~mask), "a" (p) 311e5a9f6adSMax Filippov : "memory"); 312e5a9f6adSMax Filippov 313e5a9f6adSMax Filippov return tmp & mask; 314e5a9f6adSMax Filippov } 315e5a9f6adSMax Filippov 316e5a9f6adSMax Filippov static inline int 317e5a9f6adSMax Filippov test_and_change_bit(unsigned int bit, volatile unsigned long *p) 318e5a9f6adSMax Filippov { 319e5a9f6adSMax Filippov unsigned long tmp, value; 320e5a9f6adSMax Filippov unsigned long mask = 1UL << (bit & 31); 321e5a9f6adSMax Filippov 322e5a9f6adSMax Filippov p += bit >> 5; 323e5a9f6adSMax Filippov 324e5a9f6adSMax Filippov __asm__ __volatile__( 325e5a9f6adSMax Filippov "1: l32i %1, %3, 0\n" 326e5a9f6adSMax Filippov " wsr %1, scompare1\n" 327e5a9f6adSMax Filippov " xor %0, %1, %2\n" 328e5a9f6adSMax Filippov " s32c1i %0, %3, 0\n" 329e5a9f6adSMax Filippov " bne %0, %1, 1b\n" 330e5a9f6adSMax Filippov : "=&a" (tmp), "=&a" (value) 331e5a9f6adSMax Filippov : "a" (mask), "a" (p) 332e5a9f6adSMax Filippov : "memory"); 333e5a9f6adSMax Filippov 334e5a9f6adSMax Filippov return tmp & mask; 335e5a9f6adSMax Filippov } 336e5a9f6adSMax Filippov 337e5a9f6adSMax Filippov #else 338e5a9f6adSMax Filippov 339e5a9f6adSMax Filippov #include <asm-generic/bitops/atomic.h> 340e5a9f6adSMax Filippov 341e5a9f6adSMax Filippov #endif /* XCHAL_HAVE_S32C1I */ 342e5a9f6adSMax Filippov 343367b8112SChris Zankel #include <asm-generic/bitops/find.h> 344861b5ae7SAkinobu Mita #include <asm-generic/bitops/le.h> 345367b8112SChris Zankel 346148817baSAkinobu Mita #include <asm-generic/bitops/ext2-atomic-setbit.h> 347367b8112SChris Zankel 348367b8112SChris Zankel #include <asm-generic/bitops/hweight.h> 349367b8112SChris Zankel #include <asm-generic/bitops/lock.h> 350367b8112SChris Zankel #include <asm-generic/bitops/sched.h> 351367b8112SChris Zankel 352367b8112SChris Zankel #endif /* _XTENSA_BITOPS_H */ 353