1#ifndef _MICROBLAZE_BITOPS_H 2#define _MICROBLAZE_BITOPS_H 3 4/* 5 * Copyright 1992, Linus Torvalds. 6 */ 7 8#include <asm/byteorder.h> /* swab32 */ 9#include <asm/system.h> /* save_flags */ 10#include <asm-generic/bitops/fls.h> 11#include <asm-generic/bitops/__fls.h> 12#include <asm-generic/bitops/fls64.h> 13#include <asm-generic/bitops/__ffs.h> 14 15#ifdef __KERNEL__ 16/* 17 * The __ functions are not atomic 18 */ 19 20/* 21 * ffz = Find First Zero in word. Undefined if no zero exists, 22 * so code should check against ~0UL first.. 23 */ 24static inline unsigned long ffz(unsigned long word) 25{ 26 unsigned long result = 0; 27 28 while(word & 1) { 29 result++; 30 word >>= 1; 31 } 32 return result; 33} 34 35 36static inline void set_bit(int nr, volatile void *addr) 37{ 38 int * a = (int *) addr; 39 int mask; 40 unsigned long flags; 41 42 a += nr >> 5; 43 mask = 1 << (nr & 0x1f); 44 save_flags_cli(flags); 45 *a |= mask; 46 restore_flags(flags); 47} 48 49static inline void __set_bit(int nr, volatile void *addr) 50{ 51 int * a = (int *) addr; 52 int mask; 53 54 a += nr >> 5; 55 mask = 1 << (nr & 0x1f); 56 *a |= mask; 57} 58#define PLATFORM__SET_BIT 59 60/* 61 * clear_bit() doesn't provide any barrier for the compiler. 62 */ 63#define smp_mb__before_clear_bit() barrier() 64#define smp_mb__after_clear_bit() barrier() 65 66static inline void clear_bit(int nr, volatile void *addr) 67{ 68 int * a = (int *) addr; 69 int mask; 70 unsigned long flags; 71 72 a += nr >> 5; 73 mask = 1 << (nr & 0x1f); 74 save_flags_cli(flags); 75 *a &= ~mask; 76 restore_flags(flags); 77} 78 79#define __clear_bit(nr, addr) clear_bit(nr, addr) 80#define PLATFORM__CLEAR_BIT 81 82static inline void change_bit(int nr, volatile void *addr) 83{ 84 int mask; 85 unsigned long flags; 86 unsigned long *ADDR = (unsigned long *) addr; 87 88 ADDR += nr >> 5; 89 mask = 1 << (nr & 31); 90 save_flags_cli(flags); 91 *ADDR ^= mask; 92 restore_flags(flags); 93} 94 95static inline void __change_bit(int nr, volatile void *addr) 96{ 97 int mask; 98 unsigned long *ADDR = (unsigned long *) addr; 99 100 ADDR += nr >> 5; 101 mask = 1 << (nr & 31); 102 *ADDR ^= mask; 103} 104 105static inline int test_and_set_bit(int nr, volatile void *addr) 106{ 107 int mask, retval; 108 volatile unsigned int *a = (volatile unsigned int *) addr; 109 unsigned long flags; 110 111 a += nr >> 5; 112 mask = 1 << (nr & 0x1f); 113 save_flags_cli(flags); 114 retval = (mask & *a) != 0; 115 *a |= mask; 116 restore_flags(flags); 117 118 return retval; 119} 120 121static inline int __test_and_set_bit(int nr, volatile void *addr) 122{ 123 int mask, retval; 124 volatile unsigned int *a = (volatile unsigned int *) addr; 125 126 a += nr >> 5; 127 mask = 1 << (nr & 0x1f); 128 retval = (mask & *a) != 0; 129 *a |= mask; 130 return retval; 131} 132 133static inline int test_and_clear_bit(int nr, volatile void *addr) 134{ 135 int mask, retval; 136 volatile unsigned int *a = (volatile unsigned int *) addr; 137 unsigned long flags; 138 139 a += nr >> 5; 140 mask = 1 << (nr & 0x1f); 141 save_flags_cli(flags); 142 retval = (mask & *a) != 0; 143 *a &= ~mask; 144 restore_flags(flags); 145 146 return retval; 147} 148 149static inline int __test_and_clear_bit(int nr, volatile void *addr) 150{ 151 int mask, retval; 152 volatile unsigned int *a = (volatile unsigned int *) addr; 153 154 a += nr >> 5; 155 mask = 1 << (nr & 0x1f); 156 retval = (mask & *a) != 0; 157 *a &= ~mask; 158 return retval; 159} 160 161static inline int test_and_change_bit(int nr, volatile void *addr) 162{ 163 int mask, retval; 164 volatile unsigned int *a = (volatile unsigned int *) addr; 165 unsigned long flags; 166 167 a += nr >> 5; 168 mask = 1 << (nr & 0x1f); 169 save_flags_cli(flags); 170 retval = (mask & *a) != 0; 171 *a ^= mask; 172 restore_flags(flags); 173 174 return retval; 175} 176 177static inline int __test_and_change_bit(int nr, volatile void *addr) 178{ 179 int mask, retval; 180 volatile unsigned int *a = (volatile unsigned int *) addr; 181 182 a += nr >> 5; 183 mask = 1 << (nr & 0x1f); 184 retval = (mask & *a) != 0; 185 *a ^= mask; 186 return retval; 187} 188 189/* 190 * This routine doesn't need to be atomic. 191 */ 192static inline int __constant_test_bit(int nr, const volatile void *addr) 193{ 194 return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0; 195} 196 197static inline int __test_bit(int nr, volatile void *addr) 198{ 199 int * a = (int *) addr; 200 int mask; 201 202 a += nr >> 5; 203 mask = 1 << (nr & 0x1f); 204 return ((mask & *a) != 0); 205} 206 207#define test_bit(nr,addr) \ 208(__builtin_constant_p(nr) ? \ 209 __constant_test_bit((nr),(addr)) : \ 210 __test_bit((nr),(addr))) 211 212#define find_first_zero_bit(addr, size) \ 213 find_next_zero_bit((addr), (size), 0) 214 215static inline int find_next_zero_bit(void *addr, int size, int offset) 216{ 217 unsigned long *p = ((unsigned long *) addr) + (offset >> 5); 218 unsigned long result = offset & ~31UL; 219 unsigned long tmp; 220 221 if (offset >= size) 222 return size; 223 size -= result; 224 offset &= 31UL; 225 if (offset) { 226 tmp = *(p++); 227 tmp |= ~0UL >> (32-offset); 228 if (size < 32) 229 goto found_first; 230 if (~tmp) 231 goto found_middle; 232 size -= 32; 233 result += 32; 234 } 235 while (size & ~31UL) { 236 if (~(tmp = *(p++))) 237 goto found_middle; 238 result += 32; 239 size -= 32; 240 } 241 if (!size) 242 return result; 243 tmp = *p; 244 245found_first: 246 tmp |= ~0UL >> size; 247found_middle: 248 return result + ffz(tmp); 249} 250 251/* 252 * hweightN: returns the hamming weight (i.e. the number 253 * of bits set) of a N-bit word 254 */ 255 256#define hweight32(x) generic_hweight32(x) 257#define hweight16(x) generic_hweight16(x) 258#define hweight8(x) generic_hweight8(x) 259 260 261static inline int ext2_set_bit(int nr, volatile void *addr) 262{ 263 int mask, retval; 264 unsigned long flags; 265 volatile unsigned char *ADDR = (unsigned char *) addr; 266 267 ADDR += nr >> 3; 268 mask = 1 << (nr & 0x07); 269 save_flags_cli(flags); 270 retval = (mask & *ADDR) != 0; 271 *ADDR |= mask; 272 restore_flags(flags); 273 return retval; 274} 275 276static inline int ext2_clear_bit(int nr, volatile void *addr) 277{ 278 int mask, retval; 279 unsigned long flags; 280 volatile unsigned char *ADDR = (unsigned char *) addr; 281 282 ADDR += nr >> 3; 283 mask = 1 << (nr & 0x07); 284 save_flags_cli(flags); 285 retval = (mask & *ADDR) != 0; 286 *ADDR &= ~mask; 287 restore_flags(flags); 288 return retval; 289} 290 291static inline int ext2_test_bit(int nr, const volatile void *addr) 292{ 293 int mask; 294 const volatile unsigned char *ADDR = (const unsigned char *) addr; 295 296 ADDR += nr >> 3; 297 mask = 1 << (nr & 0x07); 298 return ((mask & *ADDR) != 0); 299} 300 301#define ext2_find_first_zero_bit(addr, size) \ 302 ext2_find_next_zero_bit((addr), (size), 0) 303 304static inline unsigned long ext2_find_next_zero_bit(void *addr, 305 unsigned long size, unsigned long offset) 306{ 307 unsigned long *p = ((unsigned long *) addr) + (offset >> 5); 308 unsigned long result = offset & ~31UL; 309 unsigned long tmp; 310 311 if (offset >= size) 312 return size; 313 size -= result; 314 offset &= 31UL; 315 if(offset) { 316 /* We hold the little endian value in tmp, but then the 317 * shift is illegal. So we could keep a big endian value 318 * in tmp, like this: 319 * 320 * tmp = __swab32(*(p++)); 321 * tmp |= ~0UL >> (32-offset); 322 * 323 * but this would decrease preformance, so we change the 324 * shift: 325 */ 326 tmp = *(p++); 327 tmp |= __swab32(~0UL >> (32-offset)); 328 if(size < 32) 329 goto found_first; 330 if(~tmp) 331 goto found_middle; 332 size -= 32; 333 result += 32; 334 } 335 while(size & ~31UL) { 336 if(~(tmp = *(p++))) 337 goto found_middle; 338 result += 32; 339 size -= 32; 340 } 341 if(!size) 342 return result; 343 tmp = *p; 344 345found_first: 346 /* tmp is little endian, so we would have to swab the shift, 347 * see above. But then we have to swab tmp below for ffz, so 348 * we might as well do this here. 349 */ 350 return result + ffz(__swab32(tmp) | (~0UL << size)); 351found_middle: 352 return result + ffz(__swab32(tmp)); 353} 354 355/* Bitmap functions for the minix filesystem. */ 356#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr) 357#define minix_set_bit(nr,addr) set_bit(nr,addr) 358#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr) 359#define minix_test_bit(nr,addr) test_bit(nr,addr) 360#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size) 361 362/** 363 * hweightN - returns the hamming weight of a N-bit word 364 * @x: the word to weigh 365 * 366 * The Hamming Weight of a number is the total number of bits set in it. 367 */ 368 369#define hweight32(x) generic_hweight32(x) 370#define hweight16(x) generic_hweight16(x) 371#define hweight8(x) generic_hweight8(x) 372 373#endif /* __KERNEL__ */ 374 375#endif /* _MICROBLAZE_BITOPS_H */ 376