1 /* 2 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 */ 8 9 #ifndef _ASM_BITOPS_H 10 #define _ASM_BITOPS_H 11 12 #ifndef _LINUX_BITOPS_H 13 #error only <linux/bitops.h> can be included directly 14 #endif 15 16 #ifdef __KERNEL__ 17 18 #ifndef __ASSEMBLY__ 19 20 #include <linux/types.h> 21 #include <linux/compiler.h> 22 23 /* 24 * Hardware assisted read-modify-write using ARC700 LLOCK/SCOND insns. 25 * The Kconfig glue ensures that in SMP, this is only set if the container 26 * SoC/platform has cross-core coherent LLOCK/SCOND 27 */ 28 #if defined(CONFIG_ARC_HAS_LLSC) 29 30 static inline void set_bit(unsigned long nr, volatile unsigned long *m) 31 { 32 unsigned int temp; 33 34 m += nr >> 5; 35 36 if (__builtin_constant_p(nr)) 37 nr &= 0x1f; 38 39 __asm__ __volatile__( 40 "1: llock %0, [%1] \n" 41 " bset %0, %0, %2 \n" 42 " scond %0, [%1] \n" 43 " bnz 1b \n" 44 : "=&r"(temp) 45 : "r"(m), "ir"(nr) 46 : "cc"); 47 } 48 49 static inline void clear_bit(unsigned long nr, volatile unsigned long *m) 50 { 51 unsigned int temp; 52 53 m += nr >> 5; 54 55 if (__builtin_constant_p(nr)) 56 nr &= 0x1f; 57 58 __asm__ __volatile__( 59 "1: llock %0, [%1] \n" 60 " bclr %0, %0, %2 \n" 61 " scond %0, [%1] \n" 62 " bnz 1b \n" 63 : "=&r"(temp) 64 : "r"(m), "ir"(nr) 65 : "cc"); 66 } 67 68 static inline void change_bit(unsigned long nr, volatile unsigned long *m) 69 { 70 unsigned int temp; 71 72 m += nr >> 5; 73 74 if (__builtin_constant_p(nr)) 75 nr &= 0x1f; 76 77 __asm__ __volatile__( 78 "1: llock %0, [%1] \n" 79 " bxor %0, %0, %2 \n" 80 " scond %0, [%1] \n" 81 " bnz 1b \n" 82 : "=&r"(temp) 83 : "r"(m), "ir"(nr) 84 : "cc"); 85 } 86 87 /* 88 * Semantically: 89 * Test the bit 90 * if clear 91 * set it and return 0 (old value) 92 * else 93 * return 1 (old value). 94 * 95 * Since ARC lacks a equivalent h/w primitive, the bit is set unconditionally 96 * and the old value of bit is returned 97 */ 98 static inline int test_and_set_bit(unsigned long nr, volatile unsigned long *m) 99 { 100 unsigned long old, temp; 101 102 m += nr >> 5; 103 104 if (__builtin_constant_p(nr)) 105 nr &= 0x1f; 106 107 __asm__ __volatile__( 108 "1: llock %0, [%2] \n" 109 " bset %1, %0, %3 \n" 110 " scond %1, [%2] \n" 111 " bnz 1b \n" 112 : "=&r"(old), "=&r"(temp) 113 : "r"(m), "ir"(nr) 114 : "cc"); 115 116 return (old & (1 << nr)) != 0; 117 } 118 119 static inline int 120 test_and_clear_bit(unsigned long nr, volatile unsigned long *m) 121 { 122 unsigned int old, temp; 123 124 m += nr >> 5; 125 126 if (__builtin_constant_p(nr)) 127 nr &= 0x1f; 128 129 __asm__ __volatile__( 130 "1: llock %0, [%2] \n" 131 " bclr %1, %0, %3 \n" 132 " scond %1, [%2] \n" 133 " bnz 1b \n" 134 : "=&r"(old), "=&r"(temp) 135 : "r"(m), "ir"(nr) 136 : "cc"); 137 138 return (old & (1 << nr)) != 0; 139 } 140 141 static inline int 142 test_and_change_bit(unsigned long nr, volatile unsigned long *m) 143 { 144 unsigned int old, temp; 145 146 m += nr >> 5; 147 148 if (__builtin_constant_p(nr)) 149 nr &= 0x1f; 150 151 __asm__ __volatile__( 152 "1: llock %0, [%2] \n" 153 " bxor %1, %0, %3 \n" 154 " scond %1, [%2] \n" 155 " bnz 1b \n" 156 : "=&r"(old), "=&r"(temp) 157 : "r"(m), "ir"(nr) 158 : "cc"); 159 160 return (old & (1 << nr)) != 0; 161 } 162 163 #else /* !CONFIG_ARC_HAS_LLSC */ 164 165 #include <asm/smp.h> 166 167 /* 168 * Non hardware assisted Atomic-R-M-W 169 * Locking would change to irq-disabling only (UP) and spinlocks (SMP) 170 * 171 * There's "significant" micro-optimization in writing our own variants of 172 * bitops (over generic variants) 173 * 174 * (1) The generic APIs have "signed" @nr while we have it "unsigned" 175 * This avoids extra code to be generated for pointer arithmatic, since 176 * is "not sure" that index is NOT -ve 177 * (2) Utilize the fact that ARCompact bit fidding insn (BSET/BCLR/ASL) etc 178 * only consider bottom 5 bits of @nr, so NO need to mask them off. 179 * (GCC Quirk: however for constant @nr we still need to do the masking 180 * at compile time) 181 */ 182 183 static inline void set_bit(unsigned long nr, volatile unsigned long *m) 184 { 185 unsigned long temp, flags; 186 m += nr >> 5; 187 188 if (__builtin_constant_p(nr)) 189 nr &= 0x1f; 190 191 bitops_lock(flags); 192 193 temp = *m; 194 *m = temp | (1UL << nr); 195 196 bitops_unlock(flags); 197 } 198 199 static inline void clear_bit(unsigned long nr, volatile unsigned long *m) 200 { 201 unsigned long temp, flags; 202 m += nr >> 5; 203 204 if (__builtin_constant_p(nr)) 205 nr &= 0x1f; 206 207 bitops_lock(flags); 208 209 temp = *m; 210 *m = temp & ~(1UL << nr); 211 212 bitops_unlock(flags); 213 } 214 215 static inline void change_bit(unsigned long nr, volatile unsigned long *m) 216 { 217 unsigned long temp, flags; 218 m += nr >> 5; 219 220 if (__builtin_constant_p(nr)) 221 nr &= 0x1f; 222 223 bitops_lock(flags); 224 225 temp = *m; 226 *m = temp ^ (1UL << nr); 227 228 bitops_unlock(flags); 229 } 230 231 static inline int test_and_set_bit(unsigned long nr, volatile unsigned long *m) 232 { 233 unsigned long old, flags; 234 m += nr >> 5; 235 236 if (__builtin_constant_p(nr)) 237 nr &= 0x1f; 238 239 bitops_lock(flags); 240 241 old = *m; 242 *m = old | (1 << nr); 243 244 bitops_unlock(flags); 245 246 return (old & (1 << nr)) != 0; 247 } 248 249 static inline int 250 test_and_clear_bit(unsigned long nr, volatile unsigned long *m) 251 { 252 unsigned long old, flags; 253 m += nr >> 5; 254 255 if (__builtin_constant_p(nr)) 256 nr &= 0x1f; 257 258 bitops_lock(flags); 259 260 old = *m; 261 *m = old & ~(1 << nr); 262 263 bitops_unlock(flags); 264 265 return (old & (1 << nr)) != 0; 266 } 267 268 static inline int 269 test_and_change_bit(unsigned long nr, volatile unsigned long *m) 270 { 271 unsigned long old, flags; 272 m += nr >> 5; 273 274 if (__builtin_constant_p(nr)) 275 nr &= 0x1f; 276 277 bitops_lock(flags); 278 279 old = *m; 280 *m = old ^ (1 << nr); 281 282 bitops_unlock(flags); 283 284 return (old & (1 << nr)) != 0; 285 } 286 287 #endif /* CONFIG_ARC_HAS_LLSC */ 288 289 /*************************************** 290 * Non atomic variants 291 **************************************/ 292 293 static inline void __set_bit(unsigned long nr, volatile unsigned long *m) 294 { 295 unsigned long temp; 296 m += nr >> 5; 297 298 if (__builtin_constant_p(nr)) 299 nr &= 0x1f; 300 301 temp = *m; 302 *m = temp | (1UL << nr); 303 } 304 305 static inline void __clear_bit(unsigned long nr, volatile unsigned long *m) 306 { 307 unsigned long temp; 308 m += nr >> 5; 309 310 if (__builtin_constant_p(nr)) 311 nr &= 0x1f; 312 313 temp = *m; 314 *m = temp & ~(1UL << nr); 315 } 316 317 static inline void __change_bit(unsigned long nr, volatile unsigned long *m) 318 { 319 unsigned long temp; 320 m += nr >> 5; 321 322 if (__builtin_constant_p(nr)) 323 nr &= 0x1f; 324 325 temp = *m; 326 *m = temp ^ (1UL << nr); 327 } 328 329 static inline int 330 __test_and_set_bit(unsigned long nr, volatile unsigned long *m) 331 { 332 unsigned long old; 333 m += nr >> 5; 334 335 if (__builtin_constant_p(nr)) 336 nr &= 0x1f; 337 338 old = *m; 339 *m = old | (1 << nr); 340 341 return (old & (1 << nr)) != 0; 342 } 343 344 static inline int 345 __test_and_clear_bit(unsigned long nr, volatile unsigned long *m) 346 { 347 unsigned long old; 348 m += nr >> 5; 349 350 if (__builtin_constant_p(nr)) 351 nr &= 0x1f; 352 353 old = *m; 354 *m = old & ~(1 << nr); 355 356 return (old & (1 << nr)) != 0; 357 } 358 359 static inline int 360 __test_and_change_bit(unsigned long nr, volatile unsigned long *m) 361 { 362 unsigned long old; 363 m += nr >> 5; 364 365 if (__builtin_constant_p(nr)) 366 nr &= 0x1f; 367 368 old = *m; 369 *m = old ^ (1 << nr); 370 371 return (old & (1 << nr)) != 0; 372 } 373 374 /* 375 * This routine doesn't need to be atomic. 376 */ 377 static inline int 378 __constant_test_bit(unsigned int nr, const volatile unsigned long *addr) 379 { 380 return ((1UL << (nr & 31)) & 381 (((const volatile unsigned int *)addr)[nr >> 5])) != 0; 382 } 383 384 static inline int 385 __test_bit(unsigned int nr, const volatile unsigned long *addr) 386 { 387 unsigned long mask; 388 389 addr += nr >> 5; 390 391 /* ARC700 only considers 5 bits in bit-fiddling insn */ 392 mask = 1 << nr; 393 394 return ((mask & *addr) != 0); 395 } 396 397 #define test_bit(nr, addr) (__builtin_constant_p(nr) ? \ 398 __constant_test_bit((nr), (addr)) : \ 399 __test_bit((nr), (addr))) 400 401 /* 402 * Count the number of zeros, starting from MSB 403 * Helper for fls( ) friends 404 * This is a pure count, so (1-32) or (0-31) doesn't apply 405 * It could be 0 to 32, based on num of 0's in there 406 * clz(0x8000_0000) = 0, clz(0xFFFF_FFFF)=0, clz(0) = 32, clz(1) = 31 407 */ 408 static inline __attribute__ ((const)) int clz(unsigned int x) 409 { 410 unsigned int res; 411 412 __asm__ __volatile__( 413 " norm.f %0, %1 \n" 414 " mov.n %0, 0 \n" 415 " add.p %0, %0, 1 \n" 416 : "=r"(res) 417 : "r"(x) 418 : "cc"); 419 420 return res; 421 } 422 423 static inline int constant_fls(int x) 424 { 425 int r = 32; 426 427 if (!x) 428 return 0; 429 if (!(x & 0xffff0000u)) { 430 x <<= 16; 431 r -= 16; 432 } 433 if (!(x & 0xff000000u)) { 434 x <<= 8; 435 r -= 8; 436 } 437 if (!(x & 0xf0000000u)) { 438 x <<= 4; 439 r -= 4; 440 } 441 if (!(x & 0xc0000000u)) { 442 x <<= 2; 443 r -= 2; 444 } 445 if (!(x & 0x80000000u)) { 446 x <<= 1; 447 r -= 1; 448 } 449 return r; 450 } 451 452 /* 453 * fls = Find Last Set in word 454 * @result: [1-32] 455 * fls(1) = 1, fls(0x80000000) = 32, fls(0) = 0 456 */ 457 static inline __attribute__ ((const)) int fls(unsigned long x) 458 { 459 if (__builtin_constant_p(x)) 460 return constant_fls(x); 461 462 return 32 - clz(x); 463 } 464 465 /* 466 * __fls: Similar to fls, but zero based (0-31) 467 */ 468 static inline __attribute__ ((const)) int __fls(unsigned long x) 469 { 470 if (!x) 471 return 0; 472 else 473 return fls(x) - 1; 474 } 475 476 /* 477 * ffs = Find First Set in word (LSB to MSB) 478 * @result: [1-32], 0 if all 0's 479 */ 480 #define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); }) 481 482 /* 483 * __ffs: Similar to ffs, but zero based (0-31) 484 */ 485 static inline __attribute__ ((const)) int __ffs(unsigned long word) 486 { 487 if (!word) 488 return word; 489 490 return ffs(word) - 1; 491 } 492 493 /* 494 * ffz = Find First Zero in word. 495 * @return:[0-31], 32 if all 1's 496 */ 497 #define ffz(x) __ffs(~(x)) 498 499 /* TODO does this affect uni-processor code */ 500 #define smp_mb__before_clear_bit() barrier() 501 #define smp_mb__after_clear_bit() barrier() 502 503 #include <asm-generic/bitops/hweight.h> 504 #include <asm-generic/bitops/fls64.h> 505 #include <asm-generic/bitops/sched.h> 506 #include <asm-generic/bitops/lock.h> 507 508 #include <asm-generic/bitops/find.h> 509 #include <asm-generic/bitops/le.h> 510 #include <asm-generic/bitops/ext2-atomic-setbit.h> 511 512 #endif /* !__ASSEMBLY__ */ 513 514 #endif /* __KERNEL__ */ 515 516 #endif 517