1819833afSPeter Tyser #ifndef _MICROBLAZE_BITOPS_H 2819833afSPeter Tyser #define _MICROBLAZE_BITOPS_H 3819833afSPeter Tyser 4819833afSPeter Tyser /* 5819833afSPeter Tyser * Copyright 1992, Linus Torvalds. 6819833afSPeter Tyser */ 7819833afSPeter Tyser 8819833afSPeter Tyser #include <linux/config.h> 9819833afSPeter Tyser #include <asm/byteorder.h> /* swab32 */ 10819833afSPeter Tyser #include <asm/system.h> /* save_flags */ 11819833afSPeter Tyser 12819833afSPeter Tyser #ifdef __KERNEL__ 13819833afSPeter Tyser /* 14819833afSPeter Tyser * Function prototypes to keep gcc -Wall happy 15819833afSPeter Tyser */ 16819833afSPeter Tyser 17819833afSPeter Tyser /* 18819833afSPeter Tyser * The __ functions are not atomic 19819833afSPeter Tyser */ 20819833afSPeter Tyser 21819833afSPeter Tyser extern void set_bit(int nr, volatile void * addr); 22819833afSPeter Tyser extern void __set_bit(int nr, volatile void * addr); 23819833afSPeter Tyser 24819833afSPeter Tyser extern void clear_bit(int nr, volatile void * addr); 25819833afSPeter Tyser #define __clear_bit(nr, addr) clear_bit(nr, addr) 26819833afSPeter Tyser #define PLATFORM__CLEAR_BIT 27819833afSPeter Tyser 28819833afSPeter Tyser extern void change_bit(int nr, volatile void * addr); 29819833afSPeter Tyser extern void __change_bit(int nr, volatile void * addr); 30819833afSPeter Tyser extern int test_and_set_bit(int nr, volatile void * addr); 31819833afSPeter Tyser extern int __test_and_set_bit(int nr, volatile void * addr); 32819833afSPeter Tyser extern int test_and_clear_bit(int nr, volatile void * addr); 33819833afSPeter Tyser extern int __test_and_clear_bit(int nr, volatile void * addr); 34819833afSPeter Tyser extern int test_and_change_bit(int nr, volatile void * addr); 35819833afSPeter Tyser extern int __test_and_change_bit(int nr, volatile void * addr); 36819833afSPeter Tyser extern int __constant_test_bit(int nr, const volatile void * addr); 37819833afSPeter Tyser extern int __test_bit(int nr, volatile void * addr); 38819833afSPeter Tyser extern int find_first_zero_bit(void * addr, unsigned size); 39819833afSPeter Tyser extern int find_next_zero_bit (void * addr, int size, int offset); 40819833afSPeter Tyser 41819833afSPeter Tyser /* 42819833afSPeter Tyser * ffz = Find First Zero in word. Undefined if no zero exists, 43819833afSPeter Tyser * so code should check against ~0UL first.. 44819833afSPeter Tyser */ 45819833afSPeter Tyser extern __inline__ unsigned long ffz(unsigned long word) 46819833afSPeter Tyser { 47819833afSPeter Tyser unsigned long result = 0; 48819833afSPeter Tyser 49819833afSPeter Tyser while(word & 1) { 50819833afSPeter Tyser result++; 51819833afSPeter Tyser word >>= 1; 52819833afSPeter Tyser } 53819833afSPeter Tyser return result; 54819833afSPeter Tyser } 55819833afSPeter Tyser 56819833afSPeter Tyser 57819833afSPeter Tyser extern __inline__ void set_bit(int nr, volatile void * addr) 58819833afSPeter Tyser { 59819833afSPeter Tyser int * a = (int *) addr; 60819833afSPeter Tyser int mask; 61819833afSPeter Tyser unsigned long flags; 62819833afSPeter Tyser 63819833afSPeter Tyser a += nr >> 5; 64819833afSPeter Tyser mask = 1 << (nr & 0x1f); 65819833afSPeter Tyser save_flags_cli(flags); 66819833afSPeter Tyser *a |= mask; 67819833afSPeter Tyser restore_flags(flags); 68819833afSPeter Tyser } 69819833afSPeter Tyser 70819833afSPeter Tyser extern __inline__ void __set_bit(int nr, volatile void * addr) 71819833afSPeter Tyser { 72819833afSPeter Tyser int * a = (int *) addr; 73819833afSPeter Tyser int mask; 74819833afSPeter Tyser 75819833afSPeter Tyser a += nr >> 5; 76819833afSPeter Tyser mask = 1 << (nr & 0x1f); 77819833afSPeter Tyser *a |= mask; 78819833afSPeter Tyser } 79819833afSPeter Tyser #define PLATFORM__SET_BIT 80819833afSPeter Tyser 81819833afSPeter Tyser /* 82819833afSPeter Tyser * clear_bit() doesn't provide any barrier for the compiler. 83819833afSPeter Tyser */ 84819833afSPeter Tyser #define smp_mb__before_clear_bit() barrier() 85819833afSPeter Tyser #define smp_mb__after_clear_bit() barrier() 86819833afSPeter Tyser 87819833afSPeter Tyser extern __inline__ void clear_bit(int nr, volatile void * addr) 88819833afSPeter Tyser { 89819833afSPeter Tyser int * a = (int *) addr; 90819833afSPeter Tyser int mask; 91819833afSPeter Tyser unsigned long flags; 92819833afSPeter Tyser 93819833afSPeter Tyser a += nr >> 5; 94819833afSPeter Tyser mask = 1 << (nr & 0x1f); 95819833afSPeter Tyser save_flags_cli(flags); 96819833afSPeter Tyser *a &= ~mask; 97819833afSPeter Tyser restore_flags(flags); 98819833afSPeter Tyser } 99819833afSPeter Tyser 100819833afSPeter Tyser extern __inline__ void change_bit(int nr, volatile void * addr) 101819833afSPeter Tyser { 102819833afSPeter Tyser int mask; 103819833afSPeter Tyser unsigned long flags; 104819833afSPeter Tyser unsigned long *ADDR = (unsigned long *) addr; 105819833afSPeter Tyser 106819833afSPeter Tyser ADDR += nr >> 5; 107819833afSPeter Tyser mask = 1 << (nr & 31); 108819833afSPeter Tyser save_flags_cli(flags); 109819833afSPeter Tyser *ADDR ^= mask; 110819833afSPeter Tyser restore_flags(flags); 111819833afSPeter Tyser } 112819833afSPeter Tyser 113819833afSPeter Tyser extern __inline__ void __change_bit(int nr, volatile void * addr) 114819833afSPeter Tyser { 115819833afSPeter Tyser int mask; 116819833afSPeter Tyser unsigned long *ADDR = (unsigned long *) addr; 117819833afSPeter Tyser 118819833afSPeter Tyser ADDR += nr >> 5; 119819833afSPeter Tyser mask = 1 << (nr & 31); 120819833afSPeter Tyser *ADDR ^= mask; 121819833afSPeter Tyser } 122819833afSPeter Tyser 123819833afSPeter Tyser extern __inline__ int test_and_set_bit(int nr, volatile void * addr) 124819833afSPeter Tyser { 125819833afSPeter Tyser int mask, retval; 126819833afSPeter Tyser volatile unsigned int *a = (volatile unsigned int *) addr; 127819833afSPeter Tyser unsigned long flags; 128819833afSPeter Tyser 129819833afSPeter Tyser a += nr >> 5; 130819833afSPeter Tyser mask = 1 << (nr & 0x1f); 131819833afSPeter Tyser save_flags_cli(flags); 132819833afSPeter Tyser retval = (mask & *a) != 0; 133819833afSPeter Tyser *a |= mask; 134819833afSPeter Tyser restore_flags(flags); 135819833afSPeter Tyser 136819833afSPeter Tyser return retval; 137819833afSPeter Tyser } 138819833afSPeter Tyser 139819833afSPeter Tyser extern __inline__ int __test_and_set_bit(int nr, volatile void * addr) 140819833afSPeter Tyser { 141819833afSPeter Tyser int mask, retval; 142819833afSPeter Tyser volatile unsigned int *a = (volatile unsigned int *) addr; 143819833afSPeter Tyser 144819833afSPeter Tyser a += nr >> 5; 145819833afSPeter Tyser mask = 1 << (nr & 0x1f); 146819833afSPeter Tyser retval = (mask & *a) != 0; 147819833afSPeter Tyser *a |= mask; 148819833afSPeter Tyser return retval; 149819833afSPeter Tyser } 150819833afSPeter Tyser 151819833afSPeter Tyser extern __inline__ int test_and_clear_bit(int nr, volatile void * addr) 152819833afSPeter Tyser { 153819833afSPeter Tyser int mask, retval; 154819833afSPeter Tyser volatile unsigned int *a = (volatile unsigned int *) addr; 155819833afSPeter Tyser unsigned long flags; 156819833afSPeter Tyser 157819833afSPeter Tyser a += nr >> 5; 158819833afSPeter Tyser mask = 1 << (nr & 0x1f); 159819833afSPeter Tyser save_flags_cli(flags); 160819833afSPeter Tyser retval = (mask & *a) != 0; 161819833afSPeter Tyser *a &= ~mask; 162819833afSPeter Tyser restore_flags(flags); 163819833afSPeter Tyser 164819833afSPeter Tyser return retval; 165819833afSPeter Tyser } 166819833afSPeter Tyser 167819833afSPeter Tyser extern __inline__ int __test_and_clear_bit(int nr, volatile void * addr) 168819833afSPeter Tyser { 169819833afSPeter Tyser int mask, retval; 170819833afSPeter Tyser volatile unsigned int *a = (volatile unsigned int *) addr; 171819833afSPeter Tyser 172819833afSPeter Tyser a += nr >> 5; 173819833afSPeter Tyser mask = 1 << (nr & 0x1f); 174819833afSPeter Tyser retval = (mask & *a) != 0; 175819833afSPeter Tyser *a &= ~mask; 176819833afSPeter Tyser return retval; 177819833afSPeter Tyser } 178819833afSPeter Tyser 179819833afSPeter Tyser extern __inline__ int test_and_change_bit(int nr, volatile void * addr) 180819833afSPeter Tyser { 181819833afSPeter Tyser int mask, retval; 182819833afSPeter Tyser volatile unsigned int *a = (volatile unsigned int *) addr; 183819833afSPeter Tyser unsigned long flags; 184819833afSPeter Tyser 185819833afSPeter Tyser a += nr >> 5; 186819833afSPeter Tyser mask = 1 << (nr & 0x1f); 187819833afSPeter Tyser save_flags_cli(flags); 188819833afSPeter Tyser retval = (mask & *a) != 0; 189819833afSPeter Tyser *a ^= mask; 190819833afSPeter Tyser restore_flags(flags); 191819833afSPeter Tyser 192819833afSPeter Tyser return retval; 193819833afSPeter Tyser } 194819833afSPeter Tyser 195819833afSPeter Tyser extern __inline__ int __test_and_change_bit(int nr, volatile void * addr) 196819833afSPeter Tyser { 197819833afSPeter Tyser int mask, retval; 198819833afSPeter Tyser volatile unsigned int *a = (volatile unsigned int *) addr; 199819833afSPeter Tyser 200819833afSPeter Tyser a += nr >> 5; 201819833afSPeter Tyser mask = 1 << (nr & 0x1f); 202819833afSPeter Tyser retval = (mask & *a) != 0; 203819833afSPeter Tyser *a ^= mask; 204819833afSPeter Tyser return retval; 205819833afSPeter Tyser } 206819833afSPeter Tyser 207819833afSPeter Tyser /* 208819833afSPeter Tyser * This routine doesn't need to be atomic. 209819833afSPeter Tyser */ 210819833afSPeter Tyser extern __inline__ int __constant_test_bit(int nr, const volatile void * addr) 211819833afSPeter Tyser { 212819833afSPeter Tyser return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0; 213819833afSPeter Tyser } 214819833afSPeter Tyser 215819833afSPeter Tyser extern __inline__ int __test_bit(int nr, volatile void * addr) 216819833afSPeter Tyser { 217819833afSPeter Tyser int * a = (int *) addr; 218819833afSPeter Tyser int mask; 219819833afSPeter Tyser 220819833afSPeter Tyser a += nr >> 5; 221819833afSPeter Tyser mask = 1 << (nr & 0x1f); 222819833afSPeter Tyser return ((mask & *a) != 0); 223819833afSPeter Tyser } 224819833afSPeter Tyser 225819833afSPeter Tyser #define test_bit(nr,addr) \ 226819833afSPeter Tyser (__builtin_constant_p(nr) ? \ 227819833afSPeter Tyser __constant_test_bit((nr),(addr)) : \ 228819833afSPeter Tyser __test_bit((nr),(addr))) 229819833afSPeter Tyser 230819833afSPeter Tyser #define find_first_zero_bit(addr, size) \ 231819833afSPeter Tyser find_next_zero_bit((addr), (size), 0) 232819833afSPeter Tyser 233819833afSPeter Tyser extern __inline__ int find_next_zero_bit (void * addr, int size, int offset) 234819833afSPeter Tyser { 235819833afSPeter Tyser unsigned long *p = ((unsigned long *) addr) + (offset >> 5); 236819833afSPeter Tyser unsigned long result = offset & ~31UL; 237819833afSPeter Tyser unsigned long tmp; 238819833afSPeter Tyser 239819833afSPeter Tyser if (offset >= size) 240819833afSPeter Tyser return size; 241819833afSPeter Tyser size -= result; 242819833afSPeter Tyser offset &= 31UL; 243819833afSPeter Tyser if (offset) { 244819833afSPeter Tyser tmp = *(p++); 245819833afSPeter Tyser tmp |= ~0UL >> (32-offset); 246819833afSPeter Tyser if (size < 32) 247819833afSPeter Tyser goto found_first; 248819833afSPeter Tyser if (~tmp) 249819833afSPeter Tyser goto found_middle; 250819833afSPeter Tyser size -= 32; 251819833afSPeter Tyser result += 32; 252819833afSPeter Tyser } 253819833afSPeter Tyser while (size & ~31UL) { 254819833afSPeter Tyser if (~(tmp = *(p++))) 255819833afSPeter Tyser goto found_middle; 256819833afSPeter Tyser result += 32; 257819833afSPeter Tyser size -= 32; 258819833afSPeter Tyser } 259819833afSPeter Tyser if (!size) 260819833afSPeter Tyser return result; 261819833afSPeter Tyser tmp = *p; 262819833afSPeter Tyser 263819833afSPeter Tyser found_first: 264819833afSPeter Tyser tmp |= ~0UL >> size; 265819833afSPeter Tyser found_middle: 266819833afSPeter Tyser return result + ffz(tmp); 267819833afSPeter Tyser } 268819833afSPeter Tyser 269819833afSPeter Tyser /* 270819833afSPeter Tyser * hweightN: returns the hamming weight (i.e. the number 271819833afSPeter Tyser * of bits set) of a N-bit word 272819833afSPeter Tyser */ 273819833afSPeter Tyser 274819833afSPeter Tyser #define hweight32(x) generic_hweight32(x) 275819833afSPeter Tyser #define hweight16(x) generic_hweight16(x) 276819833afSPeter Tyser #define hweight8(x) generic_hweight8(x) 277819833afSPeter Tyser 278819833afSPeter Tyser 279819833afSPeter Tyser extern __inline__ int ext2_set_bit(int nr, volatile void * addr) 280819833afSPeter Tyser { 281819833afSPeter Tyser int mask, retval; 282819833afSPeter Tyser unsigned long flags; 283819833afSPeter Tyser volatile unsigned char *ADDR = (unsigned char *) addr; 284819833afSPeter Tyser 285819833afSPeter Tyser ADDR += nr >> 3; 286819833afSPeter Tyser mask = 1 << (nr & 0x07); 287819833afSPeter Tyser save_flags_cli(flags); 288819833afSPeter Tyser retval = (mask & *ADDR) != 0; 289819833afSPeter Tyser *ADDR |= mask; 290819833afSPeter Tyser restore_flags(flags); 291819833afSPeter Tyser return retval; 292819833afSPeter Tyser } 293819833afSPeter Tyser 294819833afSPeter Tyser extern __inline__ int ext2_clear_bit(int nr, volatile void * addr) 295819833afSPeter Tyser { 296819833afSPeter Tyser int mask, retval; 297819833afSPeter Tyser unsigned long flags; 298819833afSPeter Tyser volatile unsigned char *ADDR = (unsigned char *) addr; 299819833afSPeter Tyser 300819833afSPeter Tyser ADDR += nr >> 3; 301819833afSPeter Tyser mask = 1 << (nr & 0x07); 302819833afSPeter Tyser save_flags_cli(flags); 303819833afSPeter Tyser retval = (mask & *ADDR) != 0; 304819833afSPeter Tyser *ADDR &= ~mask; 305819833afSPeter Tyser restore_flags(flags); 306819833afSPeter Tyser return retval; 307819833afSPeter Tyser } 308819833afSPeter Tyser 309819833afSPeter Tyser extern __inline__ int ext2_test_bit(int nr, const volatile void * addr) 310819833afSPeter Tyser { 311819833afSPeter Tyser int mask; 312819833afSPeter Tyser const volatile unsigned char *ADDR = (const unsigned char *) addr; 313819833afSPeter Tyser 314819833afSPeter Tyser ADDR += nr >> 3; 315819833afSPeter Tyser mask = 1 << (nr & 0x07); 316819833afSPeter Tyser return ((mask & *ADDR) != 0); 317819833afSPeter Tyser } 318819833afSPeter Tyser 319819833afSPeter Tyser #define ext2_find_first_zero_bit(addr, size) \ 320819833afSPeter Tyser ext2_find_next_zero_bit((addr), (size), 0) 321819833afSPeter Tyser 322*548ce4bfSMichal Simek static inline unsigned long ext2_find_next_zero_bit(void *addr, 323*548ce4bfSMichal Simek unsigned long size, unsigned long offset) 324819833afSPeter Tyser { 325819833afSPeter Tyser unsigned long *p = ((unsigned long *) addr) + (offset >> 5); 326819833afSPeter Tyser unsigned long result = offset & ~31UL; 327819833afSPeter Tyser unsigned long tmp; 328819833afSPeter Tyser 329819833afSPeter Tyser if (offset >= size) 330819833afSPeter Tyser return size; 331819833afSPeter Tyser size -= result; 332819833afSPeter Tyser offset &= 31UL; 333819833afSPeter Tyser if(offset) { 334819833afSPeter Tyser /* We hold the little endian value in tmp, but then the 335819833afSPeter Tyser * shift is illegal. So we could keep a big endian value 336819833afSPeter Tyser * in tmp, like this: 337819833afSPeter Tyser * 338819833afSPeter Tyser * tmp = __swab32(*(p++)); 339819833afSPeter Tyser * tmp |= ~0UL >> (32-offset); 340819833afSPeter Tyser * 341819833afSPeter Tyser * but this would decrease preformance, so we change the 342819833afSPeter Tyser * shift: 343819833afSPeter Tyser */ 344819833afSPeter Tyser tmp = *(p++); 345819833afSPeter Tyser tmp |= __swab32(~0UL >> (32-offset)); 346819833afSPeter Tyser if(size < 32) 347819833afSPeter Tyser goto found_first; 348819833afSPeter Tyser if(~tmp) 349819833afSPeter Tyser goto found_middle; 350819833afSPeter Tyser size -= 32; 351819833afSPeter Tyser result += 32; 352819833afSPeter Tyser } 353819833afSPeter Tyser while(size & ~31UL) { 354819833afSPeter Tyser if(~(tmp = *(p++))) 355819833afSPeter Tyser goto found_middle; 356819833afSPeter Tyser result += 32; 357819833afSPeter Tyser size -= 32; 358819833afSPeter Tyser } 359819833afSPeter Tyser if(!size) 360819833afSPeter Tyser return result; 361819833afSPeter Tyser tmp = *p; 362819833afSPeter Tyser 363819833afSPeter Tyser found_first: 364819833afSPeter Tyser /* tmp is little endian, so we would have to swab the shift, 365819833afSPeter Tyser * see above. But then we have to swab tmp below for ffz, so 366819833afSPeter Tyser * we might as well do this here. 367819833afSPeter Tyser */ 368819833afSPeter Tyser return result + ffz(__swab32(tmp) | (~0UL << size)); 369819833afSPeter Tyser found_middle: 370819833afSPeter Tyser return result + ffz(__swab32(tmp)); 371819833afSPeter Tyser } 372819833afSPeter Tyser 373819833afSPeter Tyser /* Bitmap functions for the minix filesystem. */ 374819833afSPeter Tyser #define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr) 375819833afSPeter Tyser #define minix_set_bit(nr,addr) set_bit(nr,addr) 376819833afSPeter Tyser #define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr) 377819833afSPeter Tyser #define minix_test_bit(nr,addr) test_bit(nr,addr) 378819833afSPeter Tyser #define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size) 379819833afSPeter Tyser 380819833afSPeter Tyser /** 381819833afSPeter Tyser * hweightN - returns the hamming weight of a N-bit word 382819833afSPeter Tyser * @x: the word to weigh 383819833afSPeter Tyser * 384819833afSPeter Tyser * The Hamming Weight of a number is the total number of bits set in it. 385819833afSPeter Tyser */ 386819833afSPeter Tyser 387819833afSPeter Tyser #define hweight32(x) generic_hweight32(x) 388819833afSPeter Tyser #define hweight16(x) generic_hweight16(x) 389819833afSPeter Tyser #define hweight8(x) generic_hweight8(x) 390819833afSPeter Tyser 391819833afSPeter Tyser #endif /* __KERNEL__ */ 392819833afSPeter Tyser 393819833afSPeter Tyser #endif /* _MICROBLAZE_BITOPS_H */ 394