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