1 /* SPDX-License-Identifier: GPL-2.0 */ !! 1 #ifndef _M68K_BITOPS_H 2 #ifndef __ASM_GENERIC_BITOPS_H !! 2 #define _M68K_BITOPS_H 3 #define __ASM_GENERIC_BITOPS_H << 4 << 5 /* 3 /* 6 * For the benefit of those who are trying to !! 4 * Copyright 1992, Linus Torvalds. 7 * architecture, here are some C-language equi << 8 * generate reasonable code, so take a look at << 9 * out before rolling your own buggy implement << 10 * 5 * 11 * C language equivalents written by Theodore !! 6 * This file is subject to the terms and conditions of the GNU General Public >> 7 * License. See the file COPYING in the main directory of this archive >> 8 * for more details. 12 */ 9 */ 13 10 14 #include <linux/irqflags.h> << 15 #include <linux/compiler.h> 11 #include <linux/compiler.h> 16 #include <asm/barrier.h> << 17 12 18 #include <asm-generic/bitops/__ffs.h> !! 13 /* 19 #include <asm-generic/bitops/ffz.h> !! 14 * Require 68020 or better. 20 #include <asm-generic/bitops/fls.h> !! 15 * 21 #include <asm-generic/bitops/__fls.h> !! 16 * They use the standard big-endian m680x0 bit ordering. 22 #include <asm-generic/bitops/fls64.h> !! 17 */ 23 !! 18 24 #ifndef _LINUX_BITOPS_H !! 19 #define test_and_set_bit(nr,vaddr) \ 25 #error only <linux/bitops.h> can be included d !! 20 (__builtin_constant_p(nr) ? \ 26 #endif !! 21 __constant_test_and_set_bit(nr, vaddr) : \ 27 !! 22 __generic_test_and_set_bit(nr, vaddr)) 28 #include <asm-generic/bitops/sched.h> !! 23 29 #include <asm-generic/bitops/ffs.h> !! 24 extern __inline__ int __constant_test_and_set_bit(int nr,volatile unsigned long * vaddr) 30 #include <asm-generic/bitops/hweight.h> !! 25 { 31 #include <asm-generic/bitops/lock.h> !! 26 char retval; 32 !! 27 33 #include <asm-generic/bitops/atomic.h> !! 28 __asm__ __volatile__ ("bset %2,%1; sne %0" 34 #include <asm-generic/bitops/non-atomic.h> !! 29 : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) 35 #include <asm-generic/bitops/le.h> !! 30 : "di" (nr & 7)); 36 #include <asm-generic/bitops/ext2-atomic.h> !! 31 >> 32 return retval; >> 33 } >> 34 >> 35 extern __inline__ int __generic_test_and_set_bit(int nr,volatile unsigned long * vaddr) >> 36 { >> 37 char retval; >> 38 >> 39 __asm__ __volatile__ ("bfset %2@{%1:#1}; sne %0" >> 40 : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory"); >> 41 >> 42 return retval; >> 43 } >> 44 >> 45 #define set_bit(nr,vaddr) \ >> 46 (__builtin_constant_p(nr) ? \ >> 47 __constant_set_bit(nr, vaddr) : \ >> 48 __generic_set_bit(nr, vaddr)) >> 49 >> 50 #define __set_bit(nr,vaddr) set_bit(nr,vaddr) >> 51 >> 52 extern __inline__ void __constant_set_bit(int nr, volatile unsigned long * vaddr) >> 53 { >> 54 __asm__ __volatile__ ("bset %1,%0" >> 55 : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7)); >> 56 } >> 57 >> 58 extern __inline__ void __generic_set_bit(int nr, volatile unsigned long * vaddr) >> 59 { >> 60 __asm__ __volatile__ ("bfset %1@{%0:#1}" >> 61 : : "d" (nr^31), "a" (vaddr) : "memory"); >> 62 } >> 63 >> 64 #define test_and_clear_bit(nr,vaddr) \ >> 65 (__builtin_constant_p(nr) ? \ >> 66 __constant_test_and_clear_bit(nr, vaddr) : \ >> 67 __generic_test_and_clear_bit(nr, vaddr)) >> 68 >> 69 #define __test_and_clear_bit(nr,vaddr) test_and_clear_bit(nr,vaddr) >> 70 >> 71 extern __inline__ int __constant_test_and_clear_bit(int nr, volatile unsigned long * vaddr) >> 72 { >> 73 char retval; >> 74 >> 75 __asm__ __volatile__ ("bclr %2,%1; sne %0" >> 76 : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) >> 77 : "di" (nr & 7)); >> 78 >> 79 return retval; >> 80 } >> 81 >> 82 extern __inline__ int __generic_test_and_clear_bit(int nr, volatile unsigned long * vaddr) >> 83 { >> 84 char retval; >> 85 >> 86 __asm__ __volatile__ ("bfclr %2@{%1:#1}; sne %0" >> 87 : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory"); >> 88 >> 89 return retval; >> 90 } >> 91 >> 92 /* >> 93 * clear_bit() doesn't provide any barrier for the compiler. >> 94 */ >> 95 #define smp_mb__before_clear_bit() barrier() >> 96 #define smp_mb__after_clear_bit() barrier() >> 97 >> 98 #define clear_bit(nr,vaddr) \ >> 99 (__builtin_constant_p(nr) ? \ >> 100 __constant_clear_bit(nr, vaddr) : \ >> 101 __generic_clear_bit(nr, vaddr)) >> 102 #define __clear_bit(nr,vaddr) clear_bit(nr,vaddr) >> 103 >> 104 extern __inline__ void __constant_clear_bit(int nr, volatile unsigned long * vaddr) >> 105 { >> 106 __asm__ __volatile__ ("bclr %1,%0" >> 107 : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7)); >> 108 } >> 109 >> 110 extern __inline__ void __generic_clear_bit(int nr, volatile unsigned long * vaddr) >> 111 { >> 112 __asm__ __volatile__ ("bfclr %1@{%0:#1}" >> 113 : : "d" (nr^31), "a" (vaddr) : "memory"); >> 114 } >> 115 >> 116 #define test_and_change_bit(nr,vaddr) \ >> 117 (__builtin_constant_p(nr) ? \ >> 118 __constant_test_and_change_bit(nr, vaddr) : \ >> 119 __generic_test_and_change_bit(nr, vaddr)) >> 120 >> 121 #define __test_and_change_bit(nr,vaddr) test_and_change_bit(nr,vaddr) >> 122 #define __change_bit(nr,vaddr) change_bit(nr,vaddr) >> 123 >> 124 extern __inline__ int __constant_test_and_change_bit(int nr, volatile unsigned long * vaddr) >> 125 { >> 126 char retval; >> 127 >> 128 __asm__ __volatile__ ("bchg %2,%1; sne %0" >> 129 : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) >> 130 : "di" (nr & 7)); >> 131 >> 132 return retval; >> 133 } >> 134 >> 135 extern __inline__ int __generic_test_and_change_bit(int nr, volatile unsigned long * vaddr) >> 136 { >> 137 char retval; >> 138 >> 139 __asm__ __volatile__ ("bfchg %2@{%1:#1}; sne %0" >> 140 : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory"); >> 141 >> 142 return retval; >> 143 } >> 144 >> 145 #define change_bit(nr,vaddr) \ >> 146 (__builtin_constant_p(nr) ? \ >> 147 __constant_change_bit(nr, vaddr) : \ >> 148 __generic_change_bit(nr, vaddr)) >> 149 >> 150 extern __inline__ void __constant_change_bit(int nr, volatile unsigned long * vaddr) >> 151 { >> 152 __asm__ __volatile__ ("bchg %1,%0" >> 153 : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7)); >> 154 } >> 155 >> 156 extern __inline__ void __generic_change_bit(int nr, volatile unsigned long * vaddr) >> 157 { >> 158 __asm__ __volatile__ ("bfchg %1@{%0:#1}" >> 159 : : "d" (nr^31), "a" (vaddr) : "memory"); >> 160 } >> 161 >> 162 extern __inline__ int test_bit(int nr, const volatile unsigned long * vaddr) >> 163 { >> 164 return ((1UL << (nr & 31)) & (((const volatile unsigned long *) vaddr)[nr >> 5])) != 0; >> 165 } >> 166 >> 167 extern __inline__ int find_first_zero_bit(const unsigned long *vaddr, >> 168 unsigned size) >> 169 { >> 170 const unsigned long *p = vaddr, *addr = vaddr; >> 171 unsigned long allones = ~0UL; >> 172 int res; >> 173 unsigned long num; >> 174 >> 175 if (!size) >> 176 return 0; >> 177 >> 178 size = (size >> 5) + ((size & 31) > 0); >> 179 while (*p++ == allones) >> 180 { >> 181 if (--size == 0) >> 182 return (p - addr) << 5; >> 183 } >> 184 >> 185 num = ~*--p; >> 186 __asm__ __volatile__ ("bfffo %1{#0,#0},%0" >> 187 : "=d" (res) : "d" (num & -num)); >> 188 return ((p - addr) << 5) + (res ^ 31); >> 189 } >> 190 >> 191 extern __inline__ int find_next_zero_bit (const unsigned long *vaddr, int size, >> 192 int offset) >> 193 { >> 194 const unsigned long *addr = vaddr; >> 195 const unsigned long *p = addr + (offset >> 5); >> 196 int set = 0, bit = offset & 31UL, res; >> 197 >> 198 if (offset >= size) >> 199 return size; >> 200 >> 201 if (bit) { >> 202 unsigned long num = ~*p & (~0UL << bit); >> 203 >> 204 /* Look for zero in first longword */ >> 205 __asm__ __volatile__ ("bfffo %1{#0,#0},%0" >> 206 : "=d" (res) : "d" (num & -num)); >> 207 if (res < 32) >> 208 return (offset & ~31UL) + (res ^ 31); >> 209 set = 32 - bit; >> 210 p++; >> 211 } >> 212 /* No zero yet, search remaining full bytes for a zero */ >> 213 res = find_first_zero_bit (p, size - 32 * (p - addr)); >> 214 return (offset + set + res); >> 215 } >> 216 >> 217 /* >> 218 * ffz = Find First Zero in word. Undefined if no zero exists, >> 219 * so code should check against ~0UL first.. >> 220 */ >> 221 extern __inline__ unsigned long ffz(unsigned long word) >> 222 { >> 223 int res; >> 224 >> 225 __asm__ __volatile__ ("bfffo %1{#0,#0},%0" >> 226 : "=d" (res) : "d" (~word & -~word)); >> 227 return res ^ 31; >> 228 } >> 229 >> 230 #ifdef __KERNEL__ >> 231 >> 232 /* >> 233 * ffs: find first bit set. This is defined the same way as >> 234 * the libc and compiler builtin ffs routines, therefore >> 235 * differs in spirit from the above ffz (man ffs). >> 236 */ >> 237 >> 238 static inline int ffs(int x) >> 239 { >> 240 int cnt; >> 241 >> 242 asm ("bfffo %1{#0:#0},%0" : "=d" (cnt) : "dm" (x & -x)); >> 243 >> 244 return 32 - cnt; >> 245 } >> 246 #define __ffs(x) (ffs(x) - 1) >> 247 >> 248 /* >> 249 * fls: find last bit set. >> 250 */ >> 251 >> 252 static inline int fls(int x) >> 253 { >> 254 int cnt; >> 255 >> 256 asm ("bfffo %1{#0,#0},%0" : "=d" (cnt) : "dm" (x)); >> 257 >> 258 return 32 - cnt; >> 259 } >> 260 >> 261 /* >> 262 * Every architecture must define this function. It's the fastest >> 263 * way of searching a 140-bit bitmap where the first 100 bits are >> 264 * unlikely to be set. It's guaranteed that at least one of the 140 >> 265 * bits is cleared. >> 266 */ >> 267 static inline int sched_find_first_bit(const unsigned long *b) >> 268 { >> 269 if (unlikely(b[0])) >> 270 return __ffs(b[0]); >> 271 if (unlikely(b[1])) >> 272 return __ffs(b[1]) + 32; >> 273 if (unlikely(b[2])) >> 274 return __ffs(b[2]) + 64; >> 275 if (b[3]) >> 276 return __ffs(b[3]) + 96; >> 277 return __ffs(b[4]) + 128; >> 278 } >> 279 >> 280 >> 281 /* >> 282 * hweightN: returns the hamming weight (i.e. the number >> 283 * of bits set) of a N-bit word >> 284 */ >> 285 >> 286 #define hweight32(x) generic_hweight32(x) >> 287 #define hweight16(x) generic_hweight16(x) >> 288 #define hweight8(x) generic_hweight8(x) >> 289 >> 290 /* Bitmap functions for the minix filesystem */ >> 291 >> 292 extern __inline__ int >> 293 minix_find_first_zero_bit (const void *vaddr, unsigned size) >> 294 { >> 295 const unsigned short *p = vaddr, *addr = vaddr; >> 296 int res; >> 297 unsigned short num; >> 298 >> 299 if (!size) >> 300 return 0; >> 301 >> 302 size = (size >> 4) + ((size & 15) > 0); >> 303 while (*p++ == 0xffff) >> 304 { >> 305 if (--size == 0) >> 306 return (p - addr) << 4; >> 307 } >> 308 >> 309 num = ~*--p; >> 310 __asm__ __volatile__ ("bfffo %1{#16,#16},%0" >> 311 : "=d" (res) : "d" (num & -num)); >> 312 return ((p - addr) << 4) + (res ^ 31); >> 313 } >> 314 >> 315 extern __inline__ int >> 316 minix_test_and_set_bit (int nr, volatile void *vaddr) >> 317 { >> 318 char retval; >> 319 >> 320 __asm__ __volatile__ ("bfset %2{%1:#1}; sne %0" >> 321 : "=d" (retval) : "d" (nr^15), "m" (*(volatile char *)vaddr) : "memory"); >> 322 >> 323 return retval; >> 324 } >> 325 >> 326 #define minix_set_bit(nr,addr) ((void)minix_test_and_set_bit(nr,addr)) >> 327 >> 328 extern __inline__ int >> 329 minix_test_and_clear_bit (int nr, volatile void *vaddr) >> 330 { >> 331 char retval; >> 332 >> 333 __asm__ __volatile__ ("bfclr %2{%1:#1}; sne %0" >> 334 : "=d" (retval) : "d" (nr^15), "m" (*(volatile char *) vaddr) : "memory"); >> 335 >> 336 return retval; >> 337 } >> 338 >> 339 extern __inline__ int >> 340 minix_test_bit (int nr, const volatile void *vaddr) >> 341 { >> 342 return ((1U << (nr & 15)) & (((const volatile unsigned short *) vaddr)[nr >> 4])) != 0; >> 343 } >> 344 >> 345 /* Bitmap functions for the ext2 filesystem. */ >> 346 >> 347 extern __inline__ int >> 348 ext2_set_bit (int nr, volatile void *vaddr) >> 349 { >> 350 char retval; >> 351 >> 352 __asm__ __volatile__ ("bfset %2{%1,#1}; sne %0" >> 353 : "=d" (retval) : "d" (nr^7), "m" (*(volatile char *) vaddr) : "memory"); >> 354 >> 355 return retval; >> 356 } >> 357 >> 358 extern __inline__ int >> 359 ext2_clear_bit (int nr, volatile void *vaddr) >> 360 { >> 361 char retval; >> 362 >> 363 __asm__ __volatile__ ("bfclr %2{%1,#1}; sne %0" >> 364 : "=d" (retval) : "d" (nr^7), "m" (*(volatile char *) vaddr) : "memory"); >> 365 >> 366 return retval; >> 367 } >> 368 >> 369 #define ext2_set_bit_atomic(lock, nr, addr) \ >> 370 ({ \ >> 371 int ret; \ >> 372 spin_lock(lock); \ >> 373 ret = ext2_set_bit((nr), (addr)); \ >> 374 spin_unlock(lock); \ >> 375 ret; \ >> 376 }) >> 377 >> 378 #define ext2_clear_bit_atomic(lock, nr, addr) \ >> 379 ({ \ >> 380 int ret; \ >> 381 spin_lock(lock); \ >> 382 ret = ext2_clear_bit((nr), (addr)); \ >> 383 spin_unlock(lock); \ >> 384 ret; \ >> 385 }) >> 386 >> 387 extern __inline__ int >> 388 ext2_test_bit (int nr, const volatile void *vaddr) >> 389 { >> 390 return ((1U << (nr & 7)) & (((const volatile unsigned char *) vaddr)[nr >> 3])) != 0; >> 391 } >> 392 >> 393 extern __inline__ int >> 394 ext2_find_first_zero_bit (const void *vaddr, unsigned size) >> 395 { >> 396 const unsigned long *p = vaddr, *addr = vaddr; >> 397 int res; >> 398 >> 399 if (!size) >> 400 return 0; >> 401 >> 402 size = (size >> 5) + ((size & 31) > 0); >> 403 while (*p++ == ~0UL) >> 404 { >> 405 if (--size == 0) >> 406 return (p - addr) << 5; >> 407 } >> 408 >> 409 --p; >> 410 for (res = 0; res < 32; res++) >> 411 if (!ext2_test_bit (res, p)) >> 412 break; >> 413 return (p - addr) * 32 + res; >> 414 } >> 415 >> 416 extern __inline__ int >> 417 ext2_find_next_zero_bit (const void *vaddr, unsigned size, unsigned offset) >> 418 { >> 419 const unsigned long *addr = vaddr; >> 420 const unsigned long *p = addr + (offset >> 5); >> 421 int bit = offset & 31UL, res; >> 422 >> 423 if (offset >= size) >> 424 return size; >> 425 >> 426 if (bit) { >> 427 /* Look for zero in first longword */ >> 428 for (res = bit; res < 32; res++) >> 429 if (!ext2_test_bit (res, p)) >> 430 return (p - addr) * 32 + res; >> 431 p++; >> 432 } >> 433 /* No zero yet, search remaining full bytes for a zero */ >> 434 res = ext2_find_first_zero_bit (p, size - 32 * (p - addr)); >> 435 return (p - addr) * 32 + res; >> 436 } >> 437 >> 438 #endif /* __KERNEL__ */ 37 439 38 #endif /* __ASM_GENERIC_BITOPS_H */ !! 440 #endif /* _M68K_BITOPS_H */ 39 441
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.