1#ifndef _M68K_BITOPS_H 2#define _M68K_BITOPS_H 3/* 4 * Copyright 1992, Linus Torvalds. 5 * 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. 9 */ 10 11/* 12 * Require 68020 or better. 13 * 14 * They use the standard big-endian m680x0 bit ordering. 15 */ 16 17#define test_and_set_bit(nr,vaddr) \ 18 (__builtin_constant_p(nr) ? \ 19 __constant_test_and_set_bit(nr, vaddr) : \ 20 __generic_test_and_set_bit(nr, vaddr)) 21 22extern __inline__ int __constant_test_and_set_bit(int nr,volatile void * vaddr) 23{ 24 char retval; 25 26 __asm__ __volatile__ ("bset %2,%1; sne %0" 27 : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) 28 : "di" (nr & 7)); 29 30 return retval; 31} 32 33extern __inline__ int __generic_test_and_set_bit(int nr,volatile void * vaddr) 34{ 35 char retval; 36 37 __asm__ __volatile__ ("bfset %2@{%1:#1}; sne %0" 38 : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory"); 39 40 return retval; 41} 42 43#define set_bit(nr,vaddr) \ 44 (__builtin_constant_p(nr) ? \ 45 __constant_set_bit(nr, vaddr) : \ 46 __generic_set_bit(nr, vaddr)) 47 48#define __set_bit(nr,vaddr) set_bit(nr,vaddr) 49 50extern __inline__ void __constant_set_bit(int nr, volatile void * vaddr) 51{ 52 __asm__ __volatile__ ("bset %1,%0" 53 : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7)); 54} 55 56extern __inline__ void __generic_set_bit(int nr, volatile void * vaddr) 57{ 58 __asm__ __volatile__ ("bfset %1@{%0:#1}" 59 : : "d" (nr^31), "a" (vaddr) : "memory"); 60} 61 62#define test_and_clear_bit(nr,vaddr) \ 63 (__builtin_constant_p(nr) ? \ 64 __constant_test_and_clear_bit(nr, vaddr) : \ 65 __generic_test_and_clear_bit(nr, vaddr)) 66 67#define __test_and_clear_bit(nr,vaddr) test_and_clear_bit(nr,vaddr) 68 69extern __inline__ int __constant_test_and_clear_bit(int nr, volatile void * vaddr) 70{ 71 char retval; 72 73 __asm__ __volatile__ ("bclr %2,%1; sne %0" 74 : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) 75 : "di" (nr & 7)); 76 77 return retval; 78} 79 80extern __inline__ int __generic_test_and_clear_bit(int nr, volatile void * vaddr) 81{ 82 char retval; 83 84 __asm__ __volatile__ ("bfclr %2@{%1:#1}; sne %0" 85 : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory"); 86 87 return retval; 88} 89 90/* 91 * clear_bit() doesn't provide any barrier for the compiler. 92 */ 93#define smp_mb__before_clear_bit() barrier() 94#define smp_mb__after_clear_bit() barrier() 95 96#define clear_bit(nr,vaddr) \ 97 (__builtin_constant_p(nr) ? \ 98 __constant_clear_bit(nr, vaddr) : \ 99 __generic_clear_bit(nr, vaddr)) 100 101extern __inline__ void __constant_clear_bit(int nr, volatile void * vaddr) 102{ 103 __asm__ __volatile__ ("bclr %1,%0" 104 : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7)); 105} 106 107extern __inline__ void __generic_clear_bit(int nr, volatile void * vaddr) 108{ 109 __asm__ __volatile__ ("bfclr %1@{%0:#1}" 110 : : "d" (nr^31), "a" (vaddr) : "memory"); 111} 112 113#define test_and_change_bit(nr,vaddr) \ 114 (__builtin_constant_p(nr) ? \ 115 __constant_test_and_change_bit(nr, vaddr) : \ 116 __generic_test_and_change_bit(nr, vaddr)) 117 118#define __test_and_change_bit(nr,vaddr) test_and_change_bit(nr,vaddr) 119#define __change_bit(nr,vaddr) change_bit(nr,vaddr) 120 121extern __inline__ int __constant_test_and_change_bit(int nr, volatile void * vaddr) 122{ 123 char retval; 124 125 __asm__ __volatile__ ("bchg %2,%1; sne %0" 126 : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) 127 : "di" (nr & 7)); 128 129 return retval; 130} 131 132extern __inline__ int __generic_test_and_change_bit(int nr, volatile void * vaddr) 133{ 134 char retval; 135 136 __asm__ __volatile__ ("bfchg %2@{%1:#1}; sne %0" 137 : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory"); 138 139 return retval; 140} 141 142#define change_bit(nr,vaddr) \ 143 (__builtin_constant_p(nr) ? \ 144 __constant_change_bit(nr, vaddr) : \ 145 __generic_change_bit(nr, vaddr)) 146 147extern __inline__ void __constant_change_bit(int nr, volatile void * vaddr) 148{ 149 __asm__ __volatile__ ("bchg %1,%0" 150 : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7)); 151} 152 153extern __inline__ void __generic_change_bit(int nr, volatile void * vaddr) 154{ 155 __asm__ __volatile__ ("bfchg %1@{%0:#1}" 156 : : "d" (nr^31), "a" (vaddr) : "memory"); 157} 158 159extern __inline__ int test_bit(int nr, const volatile void * vaddr) 160{ 161 return ((1UL << (nr & 31)) & (((const volatile unsigned int *) vaddr)[nr >> 5])) != 0; 162} 163 164extern __inline__ int find_first_zero_bit(void * vaddr, unsigned size) 165{ 166 unsigned long *p = vaddr, *addr = vaddr; 167 unsigned long allones = ~0UL; 168 int res; 169 unsigned long num; 170 171 if (!size) 172 return 0; 173 174 size = (size >> 5) + ((size & 31) > 0); 175 while (*p++ == allones) 176 { 177 if (--size == 0) 178 return (p - addr) << 5; 179 } 180 181 num = ~*--p; 182 __asm__ __volatile__ ("bfffo %1{#0,#0},%0" 183 : "=d" (res) : "d" (num & -num)); 184 return ((p - addr) << 5) + (res ^ 31); 185} 186 187extern __inline__ int find_next_zero_bit (void *vaddr, int size, 188 int offset) 189{ 190 unsigned long *addr = vaddr; 191 unsigned long *p = addr + (offset >> 5); 192 int set = 0, bit = offset & 31UL, res; 193 194 if (offset >= size) 195 return size; 196 197 if (bit) { 198 unsigned long num = ~*p & (~0UL << bit); 199 200 /* Look for zero in first longword */ 201 __asm__ __volatile__ ("bfffo %1{#0,#0},%0" 202 : "=d" (res) : "d" (num & -num)); 203 if (res < 32) 204 return (offset & ~31UL) + (res ^ 31); 205 set = 32 - bit; 206 p++; 207 } 208 /* No zero yet, search remaining full bytes for a zero */ 209 res = find_first_zero_bit (p, size - 32 * (p - addr)); 210 return (offset + set + res); 211} 212 213/* 214 * ffz = Find First Zero in word. Undefined if no zero exists, 215 * so code should check against ~0UL first.. 216 */ 217extern __inline__ unsigned long ffz(unsigned long word) 218{ 219 int res; 220 221 __asm__ __volatile__ ("bfffo %1{#0,#0},%0" 222 : "=d" (res) : "d" (~word & -~word)); 223 return res ^ 31; 224} 225 226#ifdef __KERNEL__ 227 228/* 229 * ffs: find first bit set. This is defined the same way as 230 * the libc and compiler builtin ffs routines, therefore 231 * differs in spirit from the above ffz (man ffs). 232 */ 233 234extern __inline__ int ffs(int x) 235{ 236 int cnt; 237 238 __asm__ __volatile__("bfffo %1{#0:#0},%0" : "=d" (cnt) : "dm" (x & -x)); 239 240 return 32 - cnt; 241} 242 243/* 244 * hweightN: returns the hamming weight (i.e. the number 245 * of bits set) of a N-bit word 246 */ 247 248#define hweight32(x) generic_hweight32(x) 249#define hweight16(x) generic_hweight16(x) 250#define hweight8(x) generic_hweight8(x) 251 252/* Bitmap functions for the minix filesystem */ 253 254extern __inline__ int 255minix_find_first_zero_bit (const void *vaddr, unsigned size) 256{ 257 const unsigned short *p = vaddr, *addr = vaddr; 258 int res; 259 unsigned short num; 260 261 if (!size) 262 return 0; 263 264 size = (size >> 4) + ((size & 15) > 0); 265 while (*p++ == 0xffff) 266 { 267 if (--size == 0) 268 return (p - addr) << 4; 269 } 270 271 num = ~*--p; 272 __asm__ __volatile__ ("bfffo %1{#16,#16},%0" 273 : "=d" (res) : "d" (num & -num)); 274 return ((p - addr) << 4) + (res ^ 31); 275} 276 277extern __inline__ int 278minix_test_and_set_bit (int nr, volatile void *vaddr) 279{ 280 char retval; 281 282 __asm__ __volatile__ ("bfset %2{%1:#1}; sne %0" 283 : "=d" (retval) : "d" (nr^15), "m" (*(volatile char *)vaddr) : "memory"); 284 285 return retval; 286} 287 288#define minix_set_bit(nr,addr) ((void)minix_test_and_set_bit(nr,addr)) 289 290extern __inline__ int 291minix_test_and_clear_bit (int nr, volatile void *vaddr) 292{ 293 char retval; 294 295 __asm__ __volatile__ ("bfclr %2{%1:#1}; sne %0" 296 : "=d" (retval) : "d" (nr^15), "m" (*(volatile char *) vaddr) : "memory"); 297 298 return retval; 299} 300 301extern __inline__ int 302minix_test_bit (int nr, const volatile void *vaddr) 303{ 304 return ((1U << (nr & 15)) & (((const volatile unsigned short *) vaddr)[nr >> 4])) != 0; 305} 306 307/* Bitmap functions for the ext2 filesystem. */ 308 309extern __inline__ int 310ext2_set_bit (int nr, volatile void *vaddr) 311{ 312 char retval; 313 314 __asm__ __volatile__ ("bfset %2{%1,#1}; sne %0" 315 : "=d" (retval) : "d" (nr^7), "m" (*(volatile char *) vaddr) : "memory"); 316 317 return retval; 318} 319 320extern __inline__ int 321ext2_clear_bit (int nr, volatile void *vaddr) 322{ 323 char retval; 324 325 __asm__ __volatile__ ("bfclr %2{%1,#1}; sne %0" 326 : "=d" (retval) : "d" (nr^7), "m" (*(volatile char *) vaddr) : "memory"); 327 328 return retval; 329} 330 331extern __inline__ int 332ext2_test_bit (int nr, const volatile void *vaddr) 333{ 334 return ((1U << (nr & 7)) & (((const volatile unsigned char *) vaddr)[nr >> 3])) != 0; 335} 336 337extern __inline__ int 338ext2_find_first_zero_bit (const void *vaddr, unsigned size) 339{ 340 const unsigned long *p = vaddr, *addr = vaddr; 341 int res; 342 343 if (!size) 344 return 0; 345 346 size = (size >> 5) + ((size & 31) > 0); 347 while (*p++ == ~0UL) 348 { 349 if (--size == 0) 350 return (p - addr) << 5; 351 } 352 353 --p; 354 for (res = 0; res < 32; res++) 355 if (!ext2_test_bit (res, p)) 356 break; 357 return (p - addr) * 32 + res; 358} 359 360extern __inline__ int 361ext2_find_next_zero_bit (const void *vaddr, unsigned size, unsigned offset) 362{ 363 const unsigned long *addr = vaddr; 364 const unsigned long *p = addr + (offset >> 5); 365 int bit = offset & 31UL, res; 366 367 if (offset >= size) 368 return size; 369 370 if (bit) { 371 /* Look for zero in first longword */ 372 for (res = bit; res < 32; res++) 373 if (!ext2_test_bit (res, p)) 374 return (p - addr) * 32 + res; 375 p++; 376 } 377 /* No zero yet, search remaining full bytes for a zero */ 378 res = ext2_find_first_zero_bit (p, size - 32 * (p - addr)); 379 return (p - addr) * 32 + res; 380} 381 382#endif /* __KERNEL__ */ 383 384#endif /* _M68K_BITOPS_H */ 385