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 */ 24 static 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 36 static 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 49 static 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 66 static 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 82 static 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 95 static 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 105 static 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 121 static 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 133 static 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 149 static 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 161 static 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 177 static 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 */ 192 static 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 197 static 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 215 static 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 245 found_first: 246 tmp |= ~0UL >> size; 247 found_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 261 static 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 276 static 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 291 static 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 304 static 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 345 found_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)); 351 found_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