18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * include/asm-xtensa/bitops.h 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Atomic operations that C can't guarantee us.Useful for resource counting etc. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 78c2ecf20Sopenharmony_ci * License. See the file "COPYING" in the main directory of this archive 88c2ecf20Sopenharmony_ci * for more details. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Copyright (C) 2001 - 2007 Tensilica Inc. 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#ifndef _XTENSA_BITOPS_H 148c2ecf20Sopenharmony_ci#define _XTENSA_BITOPS_H 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#ifndef _LINUX_BITOPS_H 178c2ecf20Sopenharmony_ci#error only <linux/bitops.h> can be included directly 188c2ecf20Sopenharmony_ci#endif 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include <asm/processor.h> 218c2ecf20Sopenharmony_ci#include <asm/byteorder.h> 228c2ecf20Sopenharmony_ci#include <asm/barrier.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include <asm-generic/bitops/non-atomic.h> 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#if XCHAL_HAVE_NSA 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic inline unsigned long __cntlz (unsigned long x) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci int lz; 318c2ecf20Sopenharmony_ci asm ("nsau %0, %1" : "=r" (lz) : "r" (x)); 328c2ecf20Sopenharmony_ci return lz; 338c2ecf20Sopenharmony_ci} 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci/* 368c2ecf20Sopenharmony_ci * ffz: Find first zero in word. Undefined if no zero exists. 378c2ecf20Sopenharmony_ci * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). 388c2ecf20Sopenharmony_ci */ 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistatic inline int ffz(unsigned long x) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci return 31 - __cntlz(~x & -~x); 438c2ecf20Sopenharmony_ci} 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci/* 468c2ecf20Sopenharmony_ci * __ffs: Find first bit set in word. Return 0 for bit 0 478c2ecf20Sopenharmony_ci */ 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistatic inline unsigned long __ffs(unsigned long x) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci return 31 - __cntlz(x & -x); 528c2ecf20Sopenharmony_ci} 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci/* 558c2ecf20Sopenharmony_ci * ffs: Find first bit set in word. This is defined the same way as 568c2ecf20Sopenharmony_ci * the libc and compiler builtin ffs routines, therefore 578c2ecf20Sopenharmony_ci * differs in spirit from the above ffz (man ffs). 588c2ecf20Sopenharmony_ci */ 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistatic inline int ffs(unsigned long x) 618c2ecf20Sopenharmony_ci{ 628c2ecf20Sopenharmony_ci return 32 - __cntlz(x & -x); 638c2ecf20Sopenharmony_ci} 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci/* 668c2ecf20Sopenharmony_ci * fls: Find last (most-significant) bit set in word. 678c2ecf20Sopenharmony_ci * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. 688c2ecf20Sopenharmony_ci */ 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistatic inline int fls (unsigned int x) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci return 32 - __cntlz(x); 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci/** 768c2ecf20Sopenharmony_ci * __fls - find last (most-significant) set bit in a long word 778c2ecf20Sopenharmony_ci * @word: the word to search 788c2ecf20Sopenharmony_ci * 798c2ecf20Sopenharmony_ci * Undefined if no set bit exists, so code should check against 0 first. 808c2ecf20Sopenharmony_ci */ 818c2ecf20Sopenharmony_cistatic inline unsigned long __fls(unsigned long word) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci return 31 - __cntlz(word); 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ci#else 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci/* Use the generic implementation if we don't have the nsa/nsau instructions. */ 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci# include <asm-generic/bitops/ffs.h> 908c2ecf20Sopenharmony_ci# include <asm-generic/bitops/__ffs.h> 918c2ecf20Sopenharmony_ci# include <asm-generic/bitops/ffz.h> 928c2ecf20Sopenharmony_ci# include <asm-generic/bitops/fls.h> 938c2ecf20Sopenharmony_ci# include <asm-generic/bitops/__fls.h> 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci#endif 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci#include <asm-generic/bitops/fls64.h> 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci#if XCHAL_HAVE_EXCLUSIVE 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci#define BIT_OP(op, insn, inv) \ 1028c2ecf20Sopenharmony_cistatic inline void op##_bit(unsigned int bit, volatile unsigned long *p)\ 1038c2ecf20Sopenharmony_ci{ \ 1048c2ecf20Sopenharmony_ci unsigned long tmp; \ 1058c2ecf20Sopenharmony_ci unsigned long mask = 1UL << (bit & 31); \ 1068c2ecf20Sopenharmony_ci \ 1078c2ecf20Sopenharmony_ci p += bit >> 5; \ 1088c2ecf20Sopenharmony_ci \ 1098c2ecf20Sopenharmony_ci __asm__ __volatile__( \ 1108c2ecf20Sopenharmony_ci "1: l32ex %[tmp], %[addr]\n" \ 1118c2ecf20Sopenharmony_ci " "insn" %[tmp], %[tmp], %[mask]\n" \ 1128c2ecf20Sopenharmony_ci " s32ex %[tmp], %[addr]\n" \ 1138c2ecf20Sopenharmony_ci " getex %[tmp]\n" \ 1148c2ecf20Sopenharmony_ci " beqz %[tmp], 1b\n" \ 1158c2ecf20Sopenharmony_ci : [tmp] "=&a" (tmp) \ 1168c2ecf20Sopenharmony_ci : [mask] "a" (inv mask), [addr] "a" (p) \ 1178c2ecf20Sopenharmony_ci : "memory"); \ 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci#define TEST_AND_BIT_OP(op, insn, inv) \ 1218c2ecf20Sopenharmony_cistatic inline int \ 1228c2ecf20Sopenharmony_citest_and_##op##_bit(unsigned int bit, volatile unsigned long *p) \ 1238c2ecf20Sopenharmony_ci{ \ 1248c2ecf20Sopenharmony_ci unsigned long tmp, value; \ 1258c2ecf20Sopenharmony_ci unsigned long mask = 1UL << (bit & 31); \ 1268c2ecf20Sopenharmony_ci \ 1278c2ecf20Sopenharmony_ci p += bit >> 5; \ 1288c2ecf20Sopenharmony_ci \ 1298c2ecf20Sopenharmony_ci __asm__ __volatile__( \ 1308c2ecf20Sopenharmony_ci "1: l32ex %[value], %[addr]\n" \ 1318c2ecf20Sopenharmony_ci " "insn" %[tmp], %[value], %[mask]\n" \ 1328c2ecf20Sopenharmony_ci " s32ex %[tmp], %[addr]\n" \ 1338c2ecf20Sopenharmony_ci " getex %[tmp]\n" \ 1348c2ecf20Sopenharmony_ci " beqz %[tmp], 1b\n" \ 1358c2ecf20Sopenharmony_ci : [tmp] "=&a" (tmp), [value] "=&a" (value) \ 1368c2ecf20Sopenharmony_ci : [mask] "a" (inv mask), [addr] "a" (p) \ 1378c2ecf20Sopenharmony_ci : "memory"); \ 1388c2ecf20Sopenharmony_ci \ 1398c2ecf20Sopenharmony_ci return value & mask; \ 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci#elif XCHAL_HAVE_S32C1I 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci#define BIT_OP(op, insn, inv) \ 1458c2ecf20Sopenharmony_cistatic inline void op##_bit(unsigned int bit, volatile unsigned long *p)\ 1468c2ecf20Sopenharmony_ci{ \ 1478c2ecf20Sopenharmony_ci unsigned long tmp, value; \ 1488c2ecf20Sopenharmony_ci unsigned long mask = 1UL << (bit & 31); \ 1498c2ecf20Sopenharmony_ci \ 1508c2ecf20Sopenharmony_ci p += bit >> 5; \ 1518c2ecf20Sopenharmony_ci \ 1528c2ecf20Sopenharmony_ci __asm__ __volatile__( \ 1538c2ecf20Sopenharmony_ci "1: l32i %[value], %[mem]\n" \ 1548c2ecf20Sopenharmony_ci " wsr %[value], scompare1\n" \ 1558c2ecf20Sopenharmony_ci " "insn" %[tmp], %[value], %[mask]\n" \ 1568c2ecf20Sopenharmony_ci " s32c1i %[tmp], %[mem]\n" \ 1578c2ecf20Sopenharmony_ci " bne %[tmp], %[value], 1b\n" \ 1588c2ecf20Sopenharmony_ci : [tmp] "=&a" (tmp), [value] "=&a" (value), \ 1598c2ecf20Sopenharmony_ci [mem] "+m" (*p) \ 1608c2ecf20Sopenharmony_ci : [mask] "a" (inv mask) \ 1618c2ecf20Sopenharmony_ci : "memory"); \ 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci#define TEST_AND_BIT_OP(op, insn, inv) \ 1658c2ecf20Sopenharmony_cistatic inline int \ 1668c2ecf20Sopenharmony_citest_and_##op##_bit(unsigned int bit, volatile unsigned long *p) \ 1678c2ecf20Sopenharmony_ci{ \ 1688c2ecf20Sopenharmony_ci unsigned long tmp, value; \ 1698c2ecf20Sopenharmony_ci unsigned long mask = 1UL << (bit & 31); \ 1708c2ecf20Sopenharmony_ci \ 1718c2ecf20Sopenharmony_ci p += bit >> 5; \ 1728c2ecf20Sopenharmony_ci \ 1738c2ecf20Sopenharmony_ci __asm__ __volatile__( \ 1748c2ecf20Sopenharmony_ci "1: l32i %[value], %[mem]\n" \ 1758c2ecf20Sopenharmony_ci " wsr %[value], scompare1\n" \ 1768c2ecf20Sopenharmony_ci " "insn" %[tmp], %[value], %[mask]\n" \ 1778c2ecf20Sopenharmony_ci " s32c1i %[tmp], %[mem]\n" \ 1788c2ecf20Sopenharmony_ci " bne %[tmp], %[value], 1b\n" \ 1798c2ecf20Sopenharmony_ci : [tmp] "=&a" (tmp), [value] "=&a" (value), \ 1808c2ecf20Sopenharmony_ci [mem] "+m" (*p) \ 1818c2ecf20Sopenharmony_ci : [mask] "a" (inv mask) \ 1828c2ecf20Sopenharmony_ci : "memory"); \ 1838c2ecf20Sopenharmony_ci \ 1848c2ecf20Sopenharmony_ci return tmp & mask; \ 1858c2ecf20Sopenharmony_ci} 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci#else 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci#define BIT_OP(op, insn, inv) 1908c2ecf20Sopenharmony_ci#define TEST_AND_BIT_OP(op, insn, inv) 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci#include <asm-generic/bitops/atomic.h> 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci#endif /* XCHAL_HAVE_S32C1I */ 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci#define BIT_OPS(op, insn, inv) \ 1978c2ecf20Sopenharmony_ci BIT_OP(op, insn, inv) \ 1988c2ecf20Sopenharmony_ci TEST_AND_BIT_OP(op, insn, inv) 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ciBIT_OPS(set, "or", ) 2018c2ecf20Sopenharmony_ciBIT_OPS(clear, "and", ~) 2028c2ecf20Sopenharmony_ciBIT_OPS(change, "xor", ) 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci#undef BIT_OPS 2058c2ecf20Sopenharmony_ci#undef BIT_OP 2068c2ecf20Sopenharmony_ci#undef TEST_AND_BIT_OP 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci#include <asm-generic/bitops/find.h> 2098c2ecf20Sopenharmony_ci#include <asm-generic/bitops/le.h> 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci#include <asm-generic/bitops/ext2-atomic-setbit.h> 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci#include <asm-generic/bitops/hweight.h> 2148c2ecf20Sopenharmony_ci#include <asm-generic/bitops/lock.h> 2158c2ecf20Sopenharmony_ci#include <asm-generic/bitops/sched.h> 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci#endif /* _XTENSA_BITOPS_H */ 218