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