1 /* 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. See the file "COPYING" in the main directory of this archive 4 * for more details. 5 * 6 * Copyright (c) 1994 - 1997, 99, 2000, 06, 07 Ralf Baechle (ralf@linux-mips.org) 7 * Copyright (c) 1999, 2000 Silicon Graphics, Inc. 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 #include <linux/bits.h> 17 #include <linux/compiler.h> 18 #include <linux/types.h> 19 #include <asm/asm.h> 20 #include <asm/barrier.h> 21 #include <asm/byteorder.h> /* sigh ... */ 22 #include <asm/compiler.h> 23 #include <asm/cpu-features.h> 24 #include <asm/sgidefs.h> 25 26 #define __bit_op(mem, insn, inputs...) do { \ 27 unsigned long __temp; \ 28 \ 29 asm volatile( \ 30 " .set push \n" \ 31 " .set " MIPS_ISA_LEVEL " \n" \ 32 " " __SYNC(full, loongson3_war) " \n" \ 33 "1: " __stringify(LONG_LL) " %0, %1 \n" \ 34 " " insn " \n" \ 35 " " __stringify(LONG_SC) " %0, %1 \n" \ 36 " " __stringify(SC_BEQZ) " %0, 1b \n" \ 37 " .set pop \n" \ 38 : "=&r"(__temp), "+" GCC_OFF_SMALL_ASM()(mem) \ 39 : inputs \ 40 : __LLSC_CLOBBER); \ 41 } while (0) 42 43 #define __test_bit_op(mem, ll_dst, insn, inputs...) ({ \ 44 unsigned long __orig, __temp; \ 45 \ 46 asm volatile( \ 47 " .set push \n" \ 48 " .set " MIPS_ISA_LEVEL " \n" \ 49 " " __SYNC(full, loongson3_war) " \n" \ 50 "1: " __stringify(LONG_LL) " " ll_dst ", %2\n" \ 51 " " insn " \n" \ 52 " " __stringify(LONG_SC) " %1, %2 \n" \ 53 " " __stringify(SC_BEQZ) " %1, 1b \n" \ 54 " .set pop \n" \ 55 : "=&r"(__orig), "=&r"(__temp), \ 56 "+" GCC_OFF_SMALL_ASM()(mem) \ 57 : inputs \ 58 : __LLSC_CLOBBER); \ 59 \ 60 __orig; \ 61 }) 62 63 /* 64 * These are the "slower" versions of the functions and are in bitops.c. 65 * These functions call raw_local_irq_{save,restore}(). 66 */ 67 void __mips_set_bit(unsigned long nr, volatile unsigned long *addr); 68 void __mips_clear_bit(unsigned long nr, volatile unsigned long *addr); 69 void __mips_change_bit(unsigned long nr, volatile unsigned long *addr); 70 int __mips_test_and_set_bit_lock(unsigned long nr, 71 volatile unsigned long *addr); 72 int __mips_test_and_clear_bit(unsigned long nr, 73 volatile unsigned long *addr); 74 int __mips_test_and_change_bit(unsigned long nr, 75 volatile unsigned long *addr); 76 bool __mips_xor_is_negative_byte(unsigned long mask, 77 volatile unsigned long *addr); 78 79 /* 80 * set_bit - Atomically set a bit in memory 81 * @nr: the bit to set 82 * @addr: the address to start counting from 83 * 84 * This function is atomic and may not be reordered. See __set_bit() 85 * if you do not require the atomic guarantees. 86 * Note that @nr may be almost arbitrarily large; this function is not 87 * restricted to acting on a single-word quantity. 88 */ 89 static inline void set_bit(unsigned long nr, volatile unsigned long *addr) 90 { 91 volatile unsigned long *m = &addr[BIT_WORD(nr)]; 92 int bit = nr % BITS_PER_LONG; 93 94 if (!kernel_uses_llsc) { 95 __mips_set_bit(nr, addr); 96 return; 97 } 98 99 if ((MIPS_ISA_REV >= 2) && __builtin_constant_p(bit) && (bit >= 16)) { 100 __bit_op(*m, __stringify(LONG_INS) " %0, %3, %2, 1", "i"(bit), "r"(~0)); 101 return; 102 } 103 104 __bit_op(*m, "or\t%0, %2", "ir"(BIT(bit))); 105 } 106 107 /* 108 * clear_bit - Clears a bit in memory 109 * @nr: Bit to clear 110 * @addr: Address to start counting from 111 * 112 * clear_bit() is atomic and may not be reordered. However, it does 113 * not contain a memory barrier, so if it is used for locking purposes, 114 * you should call smp_mb__before_atomic() and/or smp_mb__after_atomic() 115 * in order to ensure changes are visible on other processors. 116 */ 117 static inline void clear_bit(unsigned long nr, volatile unsigned long *addr) 118 { 119 volatile unsigned long *m = &addr[BIT_WORD(nr)]; 120 int bit = nr % BITS_PER_LONG; 121 122 if (!kernel_uses_llsc) { 123 __mips_clear_bit(nr, addr); 124 return; 125 } 126 127 if ((MIPS_ISA_REV >= 2) && __builtin_constant_p(bit)) { 128 __bit_op(*m, __stringify(LONG_INS) " %0, $0, %2, 1", "i"(bit)); 129 return; 130 } 131 132 __bit_op(*m, "and\t%0, %2", "ir"(~BIT(bit))); 133 } 134 135 /* 136 * clear_bit_unlock - Clears a bit in memory 137 * @nr: Bit to clear 138 * @addr: Address to start counting from 139 * 140 * clear_bit() is atomic and implies release semantics before the memory 141 * operation. It can be used for an unlock. 142 */ 143 static inline void clear_bit_unlock(unsigned long nr, volatile unsigned long *addr) 144 { 145 smp_mb__before_atomic(); 146 clear_bit(nr, addr); 147 } 148 149 /* 150 * change_bit - Toggle a bit in memory 151 * @nr: Bit to change 152 * @addr: Address to start counting from 153 * 154 * change_bit() is atomic and may not be reordered. 155 * Note that @nr may be almost arbitrarily large; this function is not 156 * restricted to acting on a single-word quantity. 157 */ 158 static inline void change_bit(unsigned long nr, volatile unsigned long *addr) 159 { 160 volatile unsigned long *m = &addr[BIT_WORD(nr)]; 161 int bit = nr % BITS_PER_LONG; 162 163 if (!kernel_uses_llsc) { 164 __mips_change_bit(nr, addr); 165 return; 166 } 167 168 __bit_op(*m, "xor\t%0, %2", "ir"(BIT(bit))); 169 } 170 171 /* 172 * test_and_set_bit_lock - Set a bit and return its old value 173 * @nr: Bit to set 174 * @addr: Address to count from 175 * 176 * This operation is atomic and implies acquire ordering semantics 177 * after the memory operation. 178 */ 179 static inline int test_and_set_bit_lock(unsigned long nr, 180 volatile unsigned long *addr) 181 { 182 volatile unsigned long *m = &addr[BIT_WORD(nr)]; 183 int bit = nr % BITS_PER_LONG; 184 unsigned long res, orig; 185 186 if (!kernel_uses_llsc) { 187 res = __mips_test_and_set_bit_lock(nr, addr); 188 } else { 189 orig = __test_bit_op(*m, "%0", 190 "or\t%1, %0, %3", 191 "ir"(BIT(bit))); 192 res = (orig & BIT(bit)) != 0; 193 } 194 195 smp_llsc_mb(); 196 197 return res; 198 } 199 200 /* 201 * test_and_set_bit - Set a bit and return its old value 202 * @nr: Bit to set 203 * @addr: Address to count from 204 * 205 * This operation is atomic and cannot be reordered. 206 * It also implies a memory barrier. 207 */ 208 static inline int test_and_set_bit(unsigned long nr, 209 volatile unsigned long *addr) 210 { 211 smp_mb__before_atomic(); 212 return test_and_set_bit_lock(nr, addr); 213 } 214 215 /* 216 * test_and_clear_bit - Clear a bit and return its old value 217 * @nr: Bit to clear 218 * @addr: Address to count from 219 * 220 * This operation is atomic and cannot be reordered. 221 * It also implies a memory barrier. 222 */ 223 static inline int test_and_clear_bit(unsigned long nr, 224 volatile unsigned long *addr) 225 { 226 volatile unsigned long *m = &addr[BIT_WORD(nr)]; 227 int bit = nr % BITS_PER_LONG; 228 unsigned long res, orig; 229 230 smp_mb__before_atomic(); 231 232 if (!kernel_uses_llsc) { 233 res = __mips_test_and_clear_bit(nr, addr); 234 } else if ((MIPS_ISA_REV >= 2) && __builtin_constant_p(nr)) { 235 res = __test_bit_op(*m, "%1", 236 __stringify(LONG_EXT) " %0, %1, %3, 1;" 237 __stringify(LONG_INS) " %1, $0, %3, 1", 238 "i"(bit)); 239 } else { 240 orig = __test_bit_op(*m, "%0", 241 "or\t%1, %0, %3;" 242 "xor\t%1, %1, %3", 243 "ir"(BIT(bit))); 244 res = (orig & BIT(bit)) != 0; 245 } 246 247 smp_llsc_mb(); 248 249 return res; 250 } 251 252 /* 253 * test_and_change_bit - Change a bit and return its old value 254 * @nr: Bit to change 255 * @addr: Address to count from 256 * 257 * This operation is atomic and cannot be reordered. 258 * It also implies a memory barrier. 259 */ 260 static inline int test_and_change_bit(unsigned long nr, 261 volatile unsigned long *addr) 262 { 263 volatile unsigned long *m = &addr[BIT_WORD(nr)]; 264 int bit = nr % BITS_PER_LONG; 265 unsigned long res, orig; 266 267 smp_mb__before_atomic(); 268 269 if (!kernel_uses_llsc) { 270 res = __mips_test_and_change_bit(nr, addr); 271 } else { 272 orig = __test_bit_op(*m, "%0", 273 "xor\t%1, %0, %3", 274 "ir"(BIT(bit))); 275 res = (orig & BIT(bit)) != 0; 276 } 277 278 smp_llsc_mb(); 279 280 return res; 281 } 282 283 static inline bool xor_unlock_is_negative_byte(unsigned long mask, 284 volatile unsigned long *p) 285 { 286 unsigned long orig; 287 bool res; 288 289 smp_mb__before_atomic(); 290 291 if (!kernel_uses_llsc) { 292 res = __mips_xor_is_negative_byte(mask, p); 293 } else { 294 orig = __test_bit_op(*p, "%0", 295 "xor\t%1, %0, %3", 296 "ir"(mask)); 297 res = (orig & BIT(7)) != 0; 298 } 299 300 smp_llsc_mb(); 301 302 return res; 303 } 304 305 #undef __bit_op 306 #undef __test_bit_op 307 308 #include <asm-generic/bitops/non-atomic.h> 309 310 /* 311 * __clear_bit_unlock - Clears a bit in memory 312 * @nr: Bit to clear 313 * @addr: Address to start counting from 314 * 315 * __clear_bit() is non-atomic and implies release semantics before the memory 316 * operation. It can be used for an unlock if no other CPUs can concurrently 317 * modify other bits in the word. 318 */ 319 static inline void __clear_bit_unlock(unsigned long nr, volatile unsigned long *addr) 320 { 321 smp_mb__before_llsc(); 322 __clear_bit(nr, addr); 323 nudge_writes(); 324 } 325 326 /* 327 * Return the bit position (0..63) of the most significant 1 bit in a word 328 * Returns -1 if no 1 bit exists 329 */ 330 static __always_inline unsigned long __fls(unsigned long word) 331 { 332 int num; 333 334 if (BITS_PER_LONG == 32 && !__builtin_constant_p(word) && 335 __builtin_constant_p(cpu_has_clo_clz) && cpu_has_clo_clz) { 336 __asm__( 337 " .set push \n" 338 " .set "MIPS_ISA_LEVEL" \n" 339 " clz %0, %1 \n" 340 " .set pop \n" 341 : "=r" (num) 342 : "r" (word)); 343 344 return 31 - num; 345 } 346 347 if (BITS_PER_LONG == 64 && !__builtin_constant_p(word) && 348 __builtin_constant_p(cpu_has_mips64) && cpu_has_mips64) { 349 __asm__( 350 " .set push \n" 351 " .set "MIPS_ISA_LEVEL" \n" 352 " dclz %0, %1 \n" 353 " .set pop \n" 354 : "=r" (num) 355 : "r" (word)); 356 357 return 63 - num; 358 } 359 360 num = BITS_PER_LONG - 1; 361 362 #if BITS_PER_LONG == 64 363 if (!(word & (~0ul << 32))) { 364 num -= 32; 365 word <<= 32; 366 } 367 #endif 368 if (!(word & (~0ul << (BITS_PER_LONG-16)))) { 369 num -= 16; 370 word <<= 16; 371 } 372 if (!(word & (~0ul << (BITS_PER_LONG-8)))) { 373 num -= 8; 374 word <<= 8; 375 } 376 if (!(word & (~0ul << (BITS_PER_LONG-4)))) { 377 num -= 4; 378 word <<= 4; 379 } 380 if (!(word & (~0ul << (BITS_PER_LONG-2)))) { 381 num -= 2; 382 word <<= 2; 383 } 384 if (!(word & (~0ul << (BITS_PER_LONG-1)))) 385 num -= 1; 386 return num; 387 } 388 389 /* 390 * __ffs - find first bit in word. 391 * @word: The word to search 392 * 393 * Returns 0..SZLONG-1 394 * Undefined if no bit exists, so code should check against 0 first. 395 */ 396 static __always_inline unsigned long __ffs(unsigned long word) 397 { 398 return __fls(word & -word); 399 } 400 401 /* 402 * fls - find last bit set. 403 * @word: The word to search 404 * 405 * This is defined the same way as ffs. 406 * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. 407 */ 408 static inline int fls(unsigned int x) 409 { 410 int r; 411 412 if (!__builtin_constant_p(x) && 413 __builtin_constant_p(cpu_has_clo_clz) && cpu_has_clo_clz) { 414 __asm__( 415 " .set push \n" 416 " .set "MIPS_ISA_LEVEL" \n" 417 " clz %0, %1 \n" 418 " .set pop \n" 419 : "=r" (x) 420 : "r" (x)); 421 422 return 32 - x; 423 } 424 425 r = 32; 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 #include <asm-generic/bitops/fls64.h> 452 453 /* 454 * ffs - find first bit set. 455 * @word: The word to search 456 * 457 * This is defined the same way as 458 * the libc and compiler builtin ffs routines, therefore 459 * differs in spirit from the below ffz (man ffs). 460 */ 461 static inline int ffs(int word) 462 { 463 if (!word) 464 return 0; 465 466 return fls(word & -word); 467 } 468 469 #include <asm-generic/bitops/ffz.h> 470 471 #ifdef __KERNEL__ 472 473 #include <asm-generic/bitops/sched.h> 474 475 #include <asm/arch_hweight.h> 476 #include <asm-generic/bitops/const_hweight.h> 477 478 #include <asm-generic/bitops/le.h> 479 #include <asm-generic/bitops/ext2-atomic.h> 480 481 #endif /* __KERNEL__ */ 482 483 #endif /* _ASM_BITOPS_H */ 484
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.