2005-04-16 15:20:36 -07:00
/* $Id: bitops.h,v 1.39 2002/01/30 01:40:00 davem Exp $
* bitops . h : Bit string operations on the V9 .
*
* Copyright 1996 , 1997 David S . Miller ( davem @ caip . rutgers . edu )
*/
# ifndef _SPARC64_BITOPS_H
# define _SPARC64_BITOPS_H
# include <linux/config.h>
# include <linux/compiler.h>
# include <asm/byteorder.h>
extern int test_and_set_bit ( unsigned long nr , volatile unsigned long * addr ) ;
extern int test_and_clear_bit ( unsigned long nr , volatile unsigned long * addr ) ;
extern int test_and_change_bit ( unsigned long nr , volatile unsigned long * addr ) ;
extern void set_bit ( unsigned long nr , volatile unsigned long * addr ) ;
extern void clear_bit ( unsigned long nr , volatile unsigned long * addr ) ;
extern void change_bit ( unsigned long nr , volatile unsigned long * addr ) ;
/* "non-atomic" versions... */
2005-07-24 19:35:28 -07:00
static inline void __set_bit ( int nr , volatile unsigned long * addr )
2005-04-16 15:20:36 -07:00
{
2005-07-24 19:35:28 -07:00
unsigned long * m = ( ( unsigned long * ) addr ) + ( nr > > 6 ) ;
2005-04-16 15:20:36 -07:00
* m | = ( 1UL < < ( nr & 63 ) ) ;
}
2005-07-24 19:35:28 -07:00
static inline void __clear_bit ( int nr , volatile unsigned long * addr )
2005-04-16 15:20:36 -07:00
{
2005-07-24 19:35:28 -07:00
unsigned long * m = ( ( unsigned long * ) addr ) + ( nr > > 6 ) ;
2005-04-16 15:20:36 -07:00
* m & = ~ ( 1UL < < ( nr & 63 ) ) ;
}
2005-07-24 19:35:28 -07:00
static inline void __change_bit ( int nr , volatile unsigned long * addr )
2005-04-16 15:20:36 -07:00
{
2005-07-24 19:35:28 -07:00
unsigned long * m = ( ( unsigned long * ) addr ) + ( nr > > 6 ) ;
2005-04-16 15:20:36 -07:00
* m ^ = ( 1UL < < ( nr & 63 ) ) ;
}
2005-07-24 19:35:28 -07:00
static inline int __test_and_set_bit ( int nr , volatile unsigned long * addr )
2005-04-16 15:20:36 -07:00
{
2005-07-24 19:35:28 -07:00
unsigned long * m = ( ( unsigned long * ) addr ) + ( nr > > 6 ) ;
unsigned long old = * m ;
unsigned long mask = ( 1UL < < ( nr & 63 ) ) ;
2005-04-16 15:20:36 -07:00
* m = ( old | mask ) ;
return ( ( old & mask ) ! = 0 ) ;
}
2005-07-24 19:35:28 -07:00
static inline int __test_and_clear_bit ( int nr , volatile unsigned long * addr )
2005-04-16 15:20:36 -07:00
{
2005-07-24 19:35:28 -07:00
unsigned long * m = ( ( unsigned long * ) addr ) + ( nr > > 6 ) ;
unsigned long old = * m ;
unsigned long mask = ( 1UL < < ( nr & 63 ) ) ;
2005-04-16 15:20:36 -07:00
* m = ( old & ~ mask ) ;
return ( ( old & mask ) ! = 0 ) ;
}
2005-07-24 19:35:28 -07:00
static inline int __test_and_change_bit ( int nr , volatile unsigned long * addr )
2005-04-16 15:20:36 -07:00
{
2005-07-24 19:35:28 -07:00
unsigned long * m = ( ( unsigned long * ) addr ) + ( nr > > 6 ) ;
unsigned long old = * m ;
unsigned long mask = ( 1UL < < ( nr & 63 ) ) ;
2005-04-16 15:20:36 -07:00
* m = ( old ^ mask ) ;
return ( ( old & mask ) ! = 0 ) ;
}
# ifdef CONFIG_SMP
2005-08-29 12:46:22 -07:00
# define smp_mb__before_clear_bit() membar_storeload_loadload()
# define smp_mb__after_clear_bit() membar_storeload_storestore()
2005-04-16 15:20:36 -07:00
# else
# define smp_mb__before_clear_bit() barrier()
# define smp_mb__after_clear_bit() barrier()
# endif
2005-07-24 19:35:28 -07:00
static inline int test_bit ( int nr , __const__ volatile unsigned long * addr )
2005-04-16 15:20:36 -07:00
{
2005-07-24 19:35:28 -07:00
return ( 1UL & ( addr [ nr > > 6 ] > > ( nr & 63 ) ) ) ! = 0UL ;
2005-04-16 15:20:36 -07:00
}
/* The easy/cheese version for now. */
2005-07-24 19:35:28 -07:00
static inline unsigned long ffz ( unsigned long word )
2005-04-16 15:20:36 -07:00
{
unsigned long result ;
result = 0 ;
while ( word & 1 ) {
result + + ;
word > > = 1 ;
}
return result ;
}
/**
* __ffs - find first bit in word .
* @ word : The word to search
*
* Undefined if no bit exists , so code should check against 0 first .
*/
2005-07-24 19:35:28 -07:00
static inline unsigned long __ffs ( unsigned long word )
2005-04-16 15:20:36 -07:00
{
unsigned long result = 0 ;
while ( ! ( word & 1UL ) ) {
result + + ;
word > > = 1 ;
}
return result ;
}
/*
* fls : find last bit set .
*/
# define fls(x) generic_fls(x)
# ifdef __KERNEL__
/*
* Every architecture must define this function . It ' s the fastest
* way of searching a 140 - bit bitmap where the first 100 bits are
* unlikely to be set . It ' s guaranteed that at least one of the 140
* bits is cleared .
*/
static inline int sched_find_first_bit ( unsigned long * b )
{
if ( unlikely ( b [ 0 ] ) )
return __ffs ( b [ 0 ] ) ;
if ( unlikely ( ( ( unsigned int ) b [ 1 ] ) ) )
return __ffs ( b [ 1 ] ) + 64 ;
if ( b [ 1 ] > > 32 )
return __ffs ( b [ 1 ] > > 32 ) + 96 ;
return __ffs ( b [ 2 ] ) + 128 ;
}
/*
* ffs : find first bit set . This is defined the same way as
* the libc and compiler builtin ffs routines , therefore
* differs in spirit from the above ffz ( man ffs ) .
*/
2005-07-24 19:35:28 -07:00
static inline int ffs ( int x )
2005-04-16 15:20:36 -07:00
{
if ( ! x )
return 0 ;
return __ffs ( ( unsigned long ) x ) + 1 ;
}
/*
* hweightN : returns the hamming weight ( i . e . the number
* of bits set ) of a N - bit word
*/
# ifdef ULTRA_HAS_POPULATION_COUNT
2005-07-24 19:35:28 -07:00
static inline unsigned int hweight64 ( unsigned long w )
2005-04-16 15:20:36 -07:00
{
unsigned int res ;
__asm__ ( " popc %1,%0 " : " =r " ( res ) : " r " ( w ) ) ;
return res ;
}
2005-07-24 19:35:28 -07:00
static inline unsigned int hweight32 ( unsigned int w )
2005-04-16 15:20:36 -07:00
{
unsigned int res ;
__asm__ ( " popc %1,%0 " : " =r " ( res ) : " r " ( w & 0xffffffff ) ) ;
return res ;
}
2005-07-24 19:35:28 -07:00
static inline unsigned int hweight16 ( unsigned int w )
2005-04-16 15:20:36 -07:00
{
unsigned int res ;
__asm__ ( " popc %1,%0 " : " =r " ( res ) : " r " ( w & 0xffff ) ) ;
return res ;
}
2005-07-24 19:35:28 -07:00
static inline unsigned int hweight8 ( unsigned int w )
2005-04-16 15:20:36 -07:00
{
unsigned int res ;
__asm__ ( " popc %1,%0 " : " =r " ( res ) : " r " ( w & 0xff ) ) ;
return res ;
}
# else
# define hweight64(x) generic_hweight64(x)
# define hweight32(x) generic_hweight32(x)
# define hweight16(x) generic_hweight16(x)
# define hweight8(x) generic_hweight8(x)
# endif
# endif /* __KERNEL__ */
/**
* find_next_bit - find the next set bit in a memory region
* @ addr : The address to base the search on
* @ offset : The bitnumber to start searching at
* @ size : The maximum size to search
*/
extern unsigned long find_next_bit ( const unsigned long * , unsigned long ,
unsigned long ) ;
/**
* find_first_bit - find the first set bit in a memory region
* @ addr : The address to start the search at
* @ size : The maximum size to search
*
* Returns the bit - number of the first set bit , not the number of the byte
* containing a bit .
*/
# define find_first_bit(addr, size) \
find_next_bit ( ( addr ) , ( size ) , 0 )
/* find_next_zero_bit() finds the first zero bit in a bit string of length
* ' size ' bits , starting the search at bit ' offset ' . This is largely based
* on Linus ' s ALPHA routines , which are pretty portable BTW .
*/
extern unsigned long find_next_zero_bit ( const unsigned long * ,
unsigned long , unsigned long ) ;
# define find_first_zero_bit(addr, size) \
find_next_zero_bit ( ( addr ) , ( size ) , 0 )
# define test_and_set_le_bit(nr,addr) \
test_and_set_bit ( ( nr ) ^ 0x38 , ( addr ) )
# define test_and_clear_le_bit(nr,addr) \
test_and_clear_bit ( ( nr ) ^ 0x38 , ( addr ) )
2005-07-24 19:35:28 -07:00
static inline int test_le_bit ( int nr , __const__ unsigned long * addr )
2005-04-16 15:20:36 -07:00
{
int mask ;
__const__ unsigned char * ADDR = ( __const__ unsigned char * ) addr ;
ADDR + = nr > > 3 ;
mask = 1 < < ( nr & 0x07 ) ;
return ( ( mask & * ADDR ) ! = 0 ) ;
}
# define find_first_zero_le_bit(addr, size) \
find_next_zero_le_bit ( ( addr ) , ( size ) , 0 )
extern unsigned long find_next_zero_le_bit ( unsigned long * , unsigned long , unsigned long ) ;
# ifdef __KERNEL__
# define __set_le_bit(nr, addr) \
__set_bit ( ( nr ) ^ 0x38 , ( addr ) )
# define __clear_le_bit(nr, addr) \
__clear_bit ( ( nr ) ^ 0x38 , ( addr ) )
# define __test_and_clear_le_bit(nr, addr) \
__test_and_clear_bit ( ( nr ) ^ 0x38 , ( addr ) )
# define __test_and_set_le_bit(nr, addr) \
__test_and_set_bit ( ( nr ) ^ 0x38 , ( addr ) )
# define ext2_set_bit(nr,addr) \
__test_and_set_le_bit ( ( nr ) , ( unsigned long * ) ( addr ) )
# define ext2_set_bit_atomic(lock,nr,addr) \
test_and_set_le_bit ( ( nr ) , ( unsigned long * ) ( addr ) )
# define ext2_clear_bit(nr,addr) \
__test_and_clear_le_bit ( ( nr ) , ( unsigned long * ) ( addr ) )
# define ext2_clear_bit_atomic(lock,nr,addr) \
test_and_clear_le_bit ( ( nr ) , ( unsigned long * ) ( addr ) )
# define ext2_test_bit(nr,addr) \
test_le_bit ( ( nr ) , ( unsigned long * ) ( addr ) )
# define ext2_find_first_zero_bit(addr, size) \
find_first_zero_le_bit ( ( unsigned long * ) ( addr ) , ( size ) )
# define ext2_find_next_zero_bit(addr, size, off) \
find_next_zero_le_bit ( ( unsigned long * ) ( addr ) , ( size ) , ( off ) )
/* Bitmap functions for the minix filesystem. */
# define minix_test_and_set_bit(nr,addr) \
test_and_set_bit ( ( nr ) , ( unsigned long * ) ( addr ) )
# define minix_set_bit(nr,addr) \
set_bit ( ( nr ) , ( unsigned long * ) ( addr ) )
# define minix_test_and_clear_bit(nr,addr) \
test_and_clear_bit ( ( nr ) , ( unsigned long * ) ( addr ) )
# define minix_test_bit(nr,addr) \
test_bit ( ( nr ) , ( unsigned long * ) ( addr ) )
# define minix_find_first_zero_bit(addr,size) \
find_first_zero_bit ( ( unsigned long * ) ( addr ) , ( size ) )
# endif /* __KERNEL__ */
# endif /* defined(_SPARC64_BITOPS_H) */