11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* bitops.h: bit operations for the Fujitsu FR-V CPUs
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For an explanation of how atomic ops work in this arch, see:
40868ff7a4215f9244037b63a2952761cbe196a07Adrian Bunk *   Documentation/frv/atomic-ops.txt
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Written by David Howells (dhowells@redhat.com)
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * modify it under the terms of the GNU General Public License
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * as published by the Free Software Foundation; either version
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2 of the License, or (at your option) any later version.
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef _ASM_BITOPS_H
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define _ASM_BITOPS_H
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/compiler.h>
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/byteorder.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef __KERNEL__
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
220624517d809b1cf53c977335c9bda4c216cbddeeJiri Slaby#ifndef _LINUX_BITOPS_H
230624517d809b1cf53c977335c9bda4c216cbddeeJiri Slaby#error only <linux/bitops.h> can be included directly
240624517d809b1cf53c977335c9bda4c216cbddeeJiri Slaby#endif
250624517d809b1cf53c977335c9bda4c216cbddeeJiri Slaby
261f6d7a93c141a473e2cff428a3dbf13b4bec9325Akinobu Mita#include <asm-generic/bitops/ffz.h>
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * clear_bit() doesn't provide any barrier for the compiler.
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define smp_mb__before_clear_bit()	barrier()
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define smp_mb__after_clear_bit()	barrier()
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
346784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
356784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyersstatic inline
366784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyersunsigned long atomic_test_and_ANDNOT_mask(unsigned long mask, volatile unsigned long *v)
376784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers{
386784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers	unsigned long old, tmp;
396784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers
406784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers	asm volatile(
416784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"0:						\n"
426784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	orcc		gr0,gr0,gr0,icc3	\n"	/* set ICC3.Z */
436784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	ckeq		icc3,cc7		\n"
446784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	ld.p		%M0,%1			\n"	/* LD.P/ORCR are atomic */
456784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	orcr		cc7,cc7,cc3		\n"	/* set CC3 to true */
466784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	and%I3		%1,%3,%2		\n"
476784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	cst.p		%2,%M0		,cc3,#1	\n"	/* if store happens... */
486784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	corcc		gr29,gr29,gr0	,cc3,#1	\n"	/* ... clear ICC3.Z */
496784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	beq		icc3,#0,0b		\n"
506784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		: "+U"(*v), "=&r"(old), "=r"(tmp)
516784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		: "NPr"(~mask)
526784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		: "memory", "cc7", "cc3", "icc3"
536784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		);
546784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers
556784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers	return old;
566784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers}
576784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers
586784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyersstatic inline
596784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyersunsigned long atomic_test_and_OR_mask(unsigned long mask, volatile unsigned long *v)
606784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers{
616784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers	unsigned long old, tmp;
626784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers
636784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers	asm volatile(
646784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"0:						\n"
656784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	orcc		gr0,gr0,gr0,icc3	\n"	/* set ICC3.Z */
666784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	ckeq		icc3,cc7		\n"
676784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	ld.p		%M0,%1			\n"	/* LD.P/ORCR are atomic */
686784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	orcr		cc7,cc7,cc3		\n"	/* set CC3 to true */
696784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	or%I3		%1,%3,%2		\n"
706784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	cst.p		%2,%M0		,cc3,#1	\n"	/* if store happens... */
716784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	corcc		gr29,gr29,gr0	,cc3,#1	\n"	/* ... clear ICC3.Z */
726784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	beq		icc3,#0,0b		\n"
736784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		: "+U"(*v), "=&r"(old), "=r"(tmp)
746784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		: "NPr"(mask)
756784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		: "memory", "cc7", "cc3", "icc3"
766784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		);
776784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers
786784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers	return old;
796784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers}
806784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers
816784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyersstatic inline
826784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyersunsigned long atomic_test_and_XOR_mask(unsigned long mask, volatile unsigned long *v)
836784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers{
846784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers	unsigned long old, tmp;
856784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers
866784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers	asm volatile(
876784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"0:						\n"
886784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	orcc		gr0,gr0,gr0,icc3	\n"	/* set ICC3.Z */
896784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	ckeq		icc3,cc7		\n"
906784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	ld.p		%M0,%1			\n"	/* LD.P/ORCR are atomic */
916784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	orcr		cc7,cc7,cc3		\n"	/* set CC3 to true */
926784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	xor%I3		%1,%3,%2		\n"
936784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	cst.p		%2,%M0		,cc3,#1	\n"	/* if store happens... */
946784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	corcc		gr29,gr29,gr0	,cc3,#1	\n"	/* ... clear ICC3.Z */
956784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		"	beq		icc3,#0,0b		\n"
966784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		: "+U"(*v), "=&r"(old), "=r"(tmp)
976784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		: "NPr"(mask)
986784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		: "memory", "cc7", "cc3", "icc3"
996784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers		);
1006784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers
1016784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers	return old;
1026784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers}
1036784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers
1046784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers#else
1056784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers
1066784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyersextern unsigned long atomic_test_and_ANDNOT_mask(unsigned long mask, volatile unsigned long *v);
1076784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyersextern unsigned long atomic_test_and_OR_mask(unsigned long mask, volatile unsigned long *v);
1086784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyersextern unsigned long atomic_test_and_XOR_mask(unsigned long mask, volatile unsigned long *v);
1096784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers
1106784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers#endif
1116784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers
1126784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers#define atomic_clear_mask(mask, v)	atomic_test_and_ANDNOT_mask((mask), (v))
1136784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers#define atomic_set_mask(mask, v)	atomic_test_and_OR_mask((mask), (v))
1146784fd5931a58559673f500a333030ceaadb69bbMathieu Desnoyers
115d2f11bf7fc630e27dfcede367399dddf40521878Justin Chenstatic inline int test_and_clear_bit(unsigned long nr, volatile void *addr)
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	volatile unsigned long *ptr = addr;
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long mask = 1UL << (nr & 31);
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ptr += nr >> 5;
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (atomic_test_and_ANDNOT_mask(mask, ptr) & mask) != 0;
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
123d2f11bf7fc630e27dfcede367399dddf40521878Justin Chenstatic inline int test_and_set_bit(unsigned long nr, volatile void *addr)
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	volatile unsigned long *ptr = addr;
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long mask = 1UL << (nr & 31);
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ptr += nr >> 5;
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (atomic_test_and_OR_mask(mask, ptr) & mask) != 0;
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131d2f11bf7fc630e27dfcede367399dddf40521878Justin Chenstatic inline int test_and_change_bit(unsigned long nr, volatile void *addr)
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	volatile unsigned long *ptr = addr;
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long mask = 1UL << (nr & 31);
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ptr += nr >> 5;
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (atomic_test_and_XOR_mask(mask, ptr) & mask) != 0;
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
139d2f11bf7fc630e27dfcede367399dddf40521878Justin Chenstatic inline void clear_bit(unsigned long nr, volatile void *addr)
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(nr, addr);
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
144d2f11bf7fc630e27dfcede367399dddf40521878Justin Chenstatic inline void set_bit(unsigned long nr, volatile void *addr)
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_set_bit(nr, addr);
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
149d2f11bf7fc630e27dfcede367399dddf40521878Justin Chenstatic inline void change_bit(unsigned long nr, volatile void *addr)
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_change_bit(nr, addr);
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
154d2f11bf7fc630e27dfcede367399dddf40521878Justin Chenstatic inline void __clear_bit(unsigned long nr, volatile void *addr)
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	volatile unsigned long *a = addr;
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int mask;
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	a += nr >> 5;
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = 1 << (nr & 31);
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*a &= ~mask;
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
164d2f11bf7fc630e27dfcede367399dddf40521878Justin Chenstatic inline void __set_bit(unsigned long nr, volatile void *addr)
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	volatile unsigned long *a = addr;
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int mask;
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	a += nr >> 5;
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = 1 << (nr & 31);
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*a |= mask;
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
174d2f11bf7fc630e27dfcede367399dddf40521878Justin Chenstatic inline void __change_bit(unsigned long nr, volatile void *addr)
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	volatile unsigned long *a = addr;
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int mask;
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	a += nr >> 5;
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = 1 << (nr & 31);
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*a ^= mask;
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
184d2f11bf7fc630e27dfcede367399dddf40521878Justin Chenstatic inline int __test_and_clear_bit(unsigned long nr, volatile void *addr)
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	volatile unsigned long *a = addr;
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int mask, retval;
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	a += nr >> 5;
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = 1 << (nr & 31);
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	retval = (mask & *a) != 0;
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*a &= ~mask;
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
196d2f11bf7fc630e27dfcede367399dddf40521878Justin Chenstatic inline int __test_and_set_bit(unsigned long nr, volatile void *addr)
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	volatile unsigned long *a = addr;
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int mask, retval;
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	a += nr >> 5;
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = 1 << (nr & 31);
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	retval = (mask & *a) != 0;
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*a |= mask;
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
208d2f11bf7fc630e27dfcede367399dddf40521878Justin Chenstatic inline int __test_and_change_bit(unsigned long nr, volatile void *addr)
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	volatile unsigned long *a = addr;
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int mask, retval;
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	a += nr >> 5;
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = 1 << (nr & 31);
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	retval = (mask & *a) != 0;
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*a ^= mask;
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine doesn't need to be atomic.
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
223d2f11bf7fc630e27dfcede367399dddf40521878Justin Chenstatic inline int
224d2f11bf7fc630e27dfcede367399dddf40521878Justin Chen__constant_test_bit(unsigned long nr, const volatile void *addr)
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
229d2f11bf7fc630e27dfcede367399dddf40521878Justin Chenstatic inline int __test_bit(unsigned long nr, const volatile void *addr)
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int 	* a = (int *) addr;
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int	mask;
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	a += nr >> 5;
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = 1 << (nr & 0x1f);
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ((mask & *a) != 0);
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define test_bit(nr,addr) \
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds(__builtin_constant_p(nr) ? \
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __constant_test_bit((nr),(addr)) : \
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __test_bit((nr),(addr)))
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2441f6d7a93c141a473e2cff428a3dbf13b4bec9325Akinobu Mita#include <asm-generic/bitops/find.h>
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24692fc707208bb2e601c24b5ab65db37bcb361b658David Howells/**
24792fc707208bb2e601c24b5ab65db37bcb361b658David Howells * fls - find last bit set
24892fc707208bb2e601c24b5ab65db37bcb361b658David Howells * @x: the word to search
24992fc707208bb2e601c24b5ab65db37bcb361b658David Howells *
25092fc707208bb2e601c24b5ab65db37bcb361b658David Howells * This is defined the same way as ffs:
25192fc707208bb2e601c24b5ab65db37bcb361b658David Howells * - return 32..1 to indicate bit 31..0 most significant bit set
25292fc707208bb2e601c24b5ab65db37bcb361b658David Howells * - return 0 to indicate no bits set
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define fls(x)						\
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds({							\
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int bit;					\
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							\
25892fc707208bb2e601c24b5ab65db37bcb361b658David Howells	asm("	subcc	%1,gr0,gr0,icc0		\n"	\
25992fc707208bb2e601c24b5ab65db37bcb361b658David Howells	    "	ckne	icc0,cc4		\n"	\
26092fc707208bb2e601c24b5ab65db37bcb361b658David Howells	    "	cscan.p	%1,gr0,%0	,cc4,#1	\n"	\
26192fc707208bb2e601c24b5ab65db37bcb361b658David Howells	    "	csub	%0,%0,%0	,cc4,#0	\n"	\
26292fc707208bb2e601c24b5ab65db37bcb361b658David Howells	    "   csub    %2,%0,%0	,cc4,#1	\n"	\
26392fc707208bb2e601c24b5ab65db37bcb361b658David Howells	    : "=&r"(bit)				\
26492fc707208bb2e601c24b5ab65db37bcb361b658David Howells	    : "r"(x), "r"(32)				\
26592fc707208bb2e601c24b5ab65db37bcb361b658David Howells	    : "icc0", "cc4"				\
26692fc707208bb2e601c24b5ab65db37bcb361b658David Howells	    );						\
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							\
26892fc707208bb2e601c24b5ab65db37bcb361b658David Howells	bit;						\
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds})
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
271a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells/**
272a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells * fls64 - find last bit set in a 64-bit value
273a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells * @n: the value to search
274a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells *
275a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells * This is defined the same way as ffs:
276a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells * - return 64..1 to indicate bit 63..0 most significant bit set
277a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells * - return 0 to indicate no bits set
278a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells */
279a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howellsstatic inline __attribute__((const))
280a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howellsint fls64(u64 n)
281a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells{
282a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells	union {
283a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells		u64 ll;
284a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells		struct { u32 h, l; };
285a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells	} _;
286a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells	int bit, x, y;
287a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells
288a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells	_.ll = n;
289a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells
290a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells	asm("	subcc.p		%3,gr0,gr0,icc0		\n"
291a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells	    "	subcc		%4,gr0,gr0,icc1		\n"
292a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells	    "	ckne		icc0,cc4		\n"
293a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells	    "	ckne		icc1,cc5		\n"
294a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells	    "	norcr		cc4,cc5,cc6		\n"
295a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells	    "	csub.p		%0,%0,%0	,cc6,1	\n"
296a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells	    "	orcr		cc5,cc4,cc4		\n"
297a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells	    "	andcr		cc4,cc5,cc4		\n"
298a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells	    "	cscan.p		%3,gr0,%0	,cc4,0	\n"
299a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells	    "   setlos		#64,%1			\n"
300a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells	    "	cscan.p		%4,gr0,%0	,cc4,1	\n"
301a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells	    "   setlos		#32,%2			\n"
302a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells	    "	csub.p		%1,%0,%0	,cc4,0	\n"
303a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells	    "	csub		%2,%0,%0	,cc4,1	\n"
304a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells	    : "=&r"(bit), "=r"(x), "=r"(y)
305a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells	    : "0r"(_.h), "r"(_.l)
306a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells	    : "icc0", "icc1", "cc4", "cc5", "cc6"
307a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells	    );
308a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells	return bit;
309a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells
310a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells}
311a8ad27d03f17e6154c61e81d4a7028c56ca6390dDavid Howells
312cf134483b2cd657039b305777215c531a1009947David Howells/**
313cf134483b2cd657039b305777215c531a1009947David Howells * ffs - find first bit set
314cf134483b2cd657039b305777215c531a1009947David Howells * @x: the word to search
315cf134483b2cd657039b305777215c531a1009947David Howells *
316cf134483b2cd657039b305777215c531a1009947David Howells * - return 32..1 to indicate bit 31..0 most least significant bit set
317cf134483b2cd657039b305777215c531a1009947David Howells * - return 0 to indicate no bits set
318cf134483b2cd657039b305777215c531a1009947David Howells */
319cf134483b2cd657039b305777215c531a1009947David Howellsstatic inline __attribute__((const))
320cf134483b2cd657039b305777215c531a1009947David Howellsint ffs(int x)
321cf134483b2cd657039b305777215c531a1009947David Howells{
322cf134483b2cd657039b305777215c531a1009947David Howells	/* Note: (x & -x) gives us a mask that is the least significant
323cf134483b2cd657039b305777215c531a1009947David Howells	 * (rightmost) 1-bit of the value in x.
324cf134483b2cd657039b305777215c531a1009947David Howells	 */
325cf134483b2cd657039b305777215c531a1009947David Howells	return fls(x & -x);
326cf134483b2cd657039b305777215c531a1009947David Howells}
327cf134483b2cd657039b305777215c531a1009947David Howells
328cf134483b2cd657039b305777215c531a1009947David Howells/**
329cf134483b2cd657039b305777215c531a1009947David Howells * __ffs - find first bit set
330cf134483b2cd657039b305777215c531a1009947David Howells * @x: the word to search
331cf134483b2cd657039b305777215c531a1009947David Howells *
332cf134483b2cd657039b305777215c531a1009947David Howells * - return 31..0 to indicate bit 31..0 most least significant bit set
333cf134483b2cd657039b305777215c531a1009947David Howells * - if no bits are set in x, the result is undefined
334cf134483b2cd657039b305777215c531a1009947David Howells */
335cf134483b2cd657039b305777215c531a1009947David Howellsstatic inline __attribute__((const))
336cf134483b2cd657039b305777215c531a1009947David Howellsint __ffs(unsigned long x)
337cf134483b2cd657039b305777215c531a1009947David Howells{
338cf134483b2cd657039b305777215c531a1009947David Howells	int bit;
339cf134483b2cd657039b305777215c531a1009947David Howells	asm("scan %1,gr0,%0" : "=r"(bit) : "r"(x & -x));
340cf134483b2cd657039b305777215c531a1009947David Howells	return 31 - bit;
341cf134483b2cd657039b305777215c531a1009947David Howells}
342cf134483b2cd657039b305777215c531a1009947David Howells
343ee38e5140bafbf40e1bd25ab917ac8db54a27799Rusty Russell/**
344ee38e5140bafbf40e1bd25ab917ac8db54a27799Rusty Russell * __fls - find last (most-significant) set bit in a long word
345ee38e5140bafbf40e1bd25ab917ac8db54a27799Rusty Russell * @word: the word to search
346ee38e5140bafbf40e1bd25ab917ac8db54a27799Rusty Russell *
347ee38e5140bafbf40e1bd25ab917ac8db54a27799Rusty Russell * Undefined if no set bit exists, so code should check against 0 first.
348ee38e5140bafbf40e1bd25ab917ac8db54a27799Rusty Russell */
349ee38e5140bafbf40e1bd25ab917ac8db54a27799Rusty Russellstatic inline unsigned long __fls(unsigned long word)
350ee38e5140bafbf40e1bd25ab917ac8db54a27799Rusty Russell{
351ee38e5140bafbf40e1bd25ab917ac8db54a27799Rusty Russell	unsigned long bit;
352ee38e5140bafbf40e1bd25ab917ac8db54a27799Rusty Russell	asm("scan %1,gr0,%0" : "=r"(bit) : "r"(word));
353ee38e5140bafbf40e1bd25ab917ac8db54a27799Rusty Russell	return bit;
354ee38e5140bafbf40e1bd25ab917ac8db54a27799Rusty Russell}
355ee38e5140bafbf40e1bd25ab917ac8db54a27799Rusty Russell
356f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells/*
357f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells * special slimline version of fls() for calculating ilog2_u32()
358f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells * - note: no protection against n == 0
359f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells */
360f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells#define ARCH_HAS_ILOG2_U32
361f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howellsstatic inline __attribute__((const))
362f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howellsint __ilog2_u32(u32 n)
363f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells{
364f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells	int bit;
365f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells	asm("scan %1,gr0,%0" : "=r"(bit) : "r"(n));
366f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells	return 31 - bit;
367f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells}
368f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells
369f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells/*
370f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells * special slimline version of fls64() for calculating ilog2_u64()
371f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells * - note: no protection against n == 0
372f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells */
373f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells#define ARCH_HAS_ILOG2_U64
374f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howellsstatic inline __attribute__((const))
375f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howellsint __ilog2_u64(u64 n)
376f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells{
377f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells	union {
378f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells		u64 ll;
379f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells		struct { u32 h, l; };
380f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells	} _;
381f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells	int bit, x, y;
382f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells
383f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells	_.ll = n;
384f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells
385f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells	asm("	subcc		%3,gr0,gr0,icc0		\n"
386f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells	    "	ckeq		icc0,cc4		\n"
387f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells	    "	cscan.p		%3,gr0,%0	,cc4,0	\n"
388f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells	    "   setlos		#63,%1			\n"
389f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells	    "	cscan.p		%4,gr0,%0	,cc4,1	\n"
390f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells	    "   setlos		#31,%2			\n"
391f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells	    "	csub.p		%1,%0,%0	,cc4,0	\n"
392f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells	    "	csub		%2,%0,%0	,cc4,1	\n"
393f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells	    : "=&r"(bit), "=r"(x), "=r"(y)
394f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells	    : "0r"(_.h), "r"(_.l)
395f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells	    : "icc0", "cc4"
396f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells	    );
397f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells	return bit;
398f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells}
399f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8David Howells
4001f6d7a93c141a473e2cff428a3dbf13b4bec9325Akinobu Mita#include <asm-generic/bitops/sched.h>
4011f6d7a93c141a473e2cff428a3dbf13b4bec9325Akinobu Mita#include <asm-generic/bitops/hweight.h>
40226333576fd0d0b52f6e4025c5aded97e188bdd44Nick Piggin#include <asm-generic/bitops/lock.h>
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
404861b5ae7cde96ca081914e21dedfa7e8a38da622Akinobu Mita#include <asm-generic/bitops/le.h>
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
406148817ba092f9f6edd35bad3c6c6b8e8f90fe2edAkinobu Mita#include <asm-generic/bitops/ext2-atomic-setbit.h>
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* __KERNEL__ */
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* _ASM_BITOPS_H */
411