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