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