162306a36Sopenharmony_ci#ifndef _M68K_BITOPS_H 262306a36Sopenharmony_ci#define _M68K_BITOPS_H 362306a36Sopenharmony_ci/* 462306a36Sopenharmony_ci * Copyright 1992, Linus Torvalds. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 762306a36Sopenharmony_ci * License. See the file COPYING in the main directory of this archive 862306a36Sopenharmony_ci * for more details. 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#ifndef _LINUX_BITOPS_H 1262306a36Sopenharmony_ci#error only <linux/bitops.h> can be included directly 1362306a36Sopenharmony_ci#endif 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <linux/compiler.h> 1662306a36Sopenharmony_ci#include <asm/barrier.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* 1962306a36Sopenharmony_ci * Bit access functions vary across the ColdFire and 68k families. 2062306a36Sopenharmony_ci * So we will break them out here, and then macro in the ones we want. 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * ColdFire - supports standard bset/bclr/bchg with register operand only 2362306a36Sopenharmony_ci * 68000 - supports standard bset/bclr/bchg with memory operand 2462306a36Sopenharmony_ci * >= 68020 - also supports the bfset/bfclr/bfchg instructions 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * Although it is possible to use only the bset/bclr/bchg with register 2762306a36Sopenharmony_ci * operands on all platforms you end up with larger generated code. 2862306a36Sopenharmony_ci * So we use the best form possible on a given platform. 2962306a36Sopenharmony_ci */ 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistatic inline void bset_reg_set_bit(int nr, volatile unsigned long *vaddr) 3262306a36Sopenharmony_ci{ 3362306a36Sopenharmony_ci char *p = (char *)vaddr + (nr ^ 31) / 8; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci __asm__ __volatile__ ("bset %1,(%0)" 3662306a36Sopenharmony_ci : 3762306a36Sopenharmony_ci : "a" (p), "di" (nr & 7) 3862306a36Sopenharmony_ci : "memory"); 3962306a36Sopenharmony_ci} 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistatic inline void bset_mem_set_bit(int nr, volatile unsigned long *vaddr) 4262306a36Sopenharmony_ci{ 4362306a36Sopenharmony_ci char *p = (char *)vaddr + (nr ^ 31) / 8; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci __asm__ __volatile__ ("bset %1,%0" 4662306a36Sopenharmony_ci : "+m" (*p) 4762306a36Sopenharmony_ci : "di" (nr & 7)); 4862306a36Sopenharmony_ci} 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic inline void bfset_mem_set_bit(int nr, volatile unsigned long *vaddr) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci __asm__ __volatile__ ("bfset %1{%0:#1}" 5362306a36Sopenharmony_ci : 5462306a36Sopenharmony_ci : "d" (nr ^ 31), "o" (*vaddr) 5562306a36Sopenharmony_ci : "memory"); 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci#if defined(CONFIG_COLDFIRE) 5962306a36Sopenharmony_ci#define set_bit(nr, vaddr) bset_reg_set_bit(nr, vaddr) 6062306a36Sopenharmony_ci#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS) 6162306a36Sopenharmony_ci#define set_bit(nr, vaddr) bset_mem_set_bit(nr, vaddr) 6262306a36Sopenharmony_ci#else 6362306a36Sopenharmony_ci#define set_bit(nr, vaddr) (__builtin_constant_p(nr) ? \ 6462306a36Sopenharmony_ci bset_mem_set_bit(nr, vaddr) : \ 6562306a36Sopenharmony_ci bfset_mem_set_bit(nr, vaddr)) 6662306a36Sopenharmony_ci#endif 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistatic __always_inline void 6962306a36Sopenharmony_ciarch___set_bit(unsigned long nr, volatile unsigned long *addr) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci set_bit(nr, addr); 7262306a36Sopenharmony_ci} 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic inline void bclr_reg_clear_bit(int nr, volatile unsigned long *vaddr) 7562306a36Sopenharmony_ci{ 7662306a36Sopenharmony_ci char *p = (char *)vaddr + (nr ^ 31) / 8; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci __asm__ __volatile__ ("bclr %1,(%0)" 7962306a36Sopenharmony_ci : 8062306a36Sopenharmony_ci : "a" (p), "di" (nr & 7) 8162306a36Sopenharmony_ci : "memory"); 8262306a36Sopenharmony_ci} 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistatic inline void bclr_mem_clear_bit(int nr, volatile unsigned long *vaddr) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci char *p = (char *)vaddr + (nr ^ 31) / 8; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci __asm__ __volatile__ ("bclr %1,%0" 8962306a36Sopenharmony_ci : "+m" (*p) 9062306a36Sopenharmony_ci : "di" (nr & 7)); 9162306a36Sopenharmony_ci} 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistatic inline void bfclr_mem_clear_bit(int nr, volatile unsigned long *vaddr) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci __asm__ __volatile__ ("bfclr %1{%0:#1}" 9662306a36Sopenharmony_ci : 9762306a36Sopenharmony_ci : "d" (nr ^ 31), "o" (*vaddr) 9862306a36Sopenharmony_ci : "memory"); 9962306a36Sopenharmony_ci} 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci#if defined(CONFIG_COLDFIRE) 10262306a36Sopenharmony_ci#define clear_bit(nr, vaddr) bclr_reg_clear_bit(nr, vaddr) 10362306a36Sopenharmony_ci#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS) 10462306a36Sopenharmony_ci#define clear_bit(nr, vaddr) bclr_mem_clear_bit(nr, vaddr) 10562306a36Sopenharmony_ci#else 10662306a36Sopenharmony_ci#define clear_bit(nr, vaddr) (__builtin_constant_p(nr) ? \ 10762306a36Sopenharmony_ci bclr_mem_clear_bit(nr, vaddr) : \ 10862306a36Sopenharmony_ci bfclr_mem_clear_bit(nr, vaddr)) 10962306a36Sopenharmony_ci#endif 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_cistatic __always_inline void 11262306a36Sopenharmony_ciarch___clear_bit(unsigned long nr, volatile unsigned long *addr) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci clear_bit(nr, addr); 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_cistatic inline void bchg_reg_change_bit(int nr, volatile unsigned long *vaddr) 11862306a36Sopenharmony_ci{ 11962306a36Sopenharmony_ci char *p = (char *)vaddr + (nr ^ 31) / 8; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci __asm__ __volatile__ ("bchg %1,(%0)" 12262306a36Sopenharmony_ci : 12362306a36Sopenharmony_ci : "a" (p), "di" (nr & 7) 12462306a36Sopenharmony_ci : "memory"); 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cistatic inline void bchg_mem_change_bit(int nr, volatile unsigned long *vaddr) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci char *p = (char *)vaddr + (nr ^ 31) / 8; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci __asm__ __volatile__ ("bchg %1,%0" 13262306a36Sopenharmony_ci : "+m" (*p) 13362306a36Sopenharmony_ci : "di" (nr & 7)); 13462306a36Sopenharmony_ci} 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistatic inline void bfchg_mem_change_bit(int nr, volatile unsigned long *vaddr) 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci __asm__ __volatile__ ("bfchg %1{%0:#1}" 13962306a36Sopenharmony_ci : 14062306a36Sopenharmony_ci : "d" (nr ^ 31), "o" (*vaddr) 14162306a36Sopenharmony_ci : "memory"); 14262306a36Sopenharmony_ci} 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci#if defined(CONFIG_COLDFIRE) 14562306a36Sopenharmony_ci#define change_bit(nr, vaddr) bchg_reg_change_bit(nr, vaddr) 14662306a36Sopenharmony_ci#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS) 14762306a36Sopenharmony_ci#define change_bit(nr, vaddr) bchg_mem_change_bit(nr, vaddr) 14862306a36Sopenharmony_ci#else 14962306a36Sopenharmony_ci#define change_bit(nr, vaddr) (__builtin_constant_p(nr) ? \ 15062306a36Sopenharmony_ci bchg_mem_change_bit(nr, vaddr) : \ 15162306a36Sopenharmony_ci bfchg_mem_change_bit(nr, vaddr)) 15262306a36Sopenharmony_ci#endif 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cistatic __always_inline void 15562306a36Sopenharmony_ciarch___change_bit(unsigned long nr, volatile unsigned long *addr) 15662306a36Sopenharmony_ci{ 15762306a36Sopenharmony_ci change_bit(nr, addr); 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci#define arch_test_bit generic_test_bit 16162306a36Sopenharmony_ci#define arch_test_bit_acquire generic_test_bit_acquire 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cistatic inline int bset_reg_test_and_set_bit(int nr, 16462306a36Sopenharmony_ci volatile unsigned long *vaddr) 16562306a36Sopenharmony_ci{ 16662306a36Sopenharmony_ci char *p = (char *)vaddr + (nr ^ 31) / 8; 16762306a36Sopenharmony_ci char retval; 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci __asm__ __volatile__ ("bset %2,(%1); sne %0" 17062306a36Sopenharmony_ci : "=d" (retval) 17162306a36Sopenharmony_ci : "a" (p), "di" (nr & 7) 17262306a36Sopenharmony_ci : "memory"); 17362306a36Sopenharmony_ci return retval; 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cistatic inline int bset_mem_test_and_set_bit(int nr, 17762306a36Sopenharmony_ci volatile unsigned long *vaddr) 17862306a36Sopenharmony_ci{ 17962306a36Sopenharmony_ci char *p = (char *)vaddr + (nr ^ 31) / 8; 18062306a36Sopenharmony_ci char retval; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci __asm__ __volatile__ ("bset %2,%1; sne %0" 18362306a36Sopenharmony_ci : "=d" (retval), "+m" (*p) 18462306a36Sopenharmony_ci : "di" (nr & 7)); 18562306a36Sopenharmony_ci return retval; 18662306a36Sopenharmony_ci} 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_cistatic inline int bfset_mem_test_and_set_bit(int nr, 18962306a36Sopenharmony_ci volatile unsigned long *vaddr) 19062306a36Sopenharmony_ci{ 19162306a36Sopenharmony_ci char retval; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci __asm__ __volatile__ ("bfset %2{%1:#1}; sne %0" 19462306a36Sopenharmony_ci : "=d" (retval) 19562306a36Sopenharmony_ci : "d" (nr ^ 31), "o" (*vaddr) 19662306a36Sopenharmony_ci : "memory"); 19762306a36Sopenharmony_ci return retval; 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci#if defined(CONFIG_COLDFIRE) 20162306a36Sopenharmony_ci#define test_and_set_bit(nr, vaddr) bset_reg_test_and_set_bit(nr, vaddr) 20262306a36Sopenharmony_ci#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS) 20362306a36Sopenharmony_ci#define test_and_set_bit(nr, vaddr) bset_mem_test_and_set_bit(nr, vaddr) 20462306a36Sopenharmony_ci#else 20562306a36Sopenharmony_ci#define test_and_set_bit(nr, vaddr) (__builtin_constant_p(nr) ? \ 20662306a36Sopenharmony_ci bset_mem_test_and_set_bit(nr, vaddr) : \ 20762306a36Sopenharmony_ci bfset_mem_test_and_set_bit(nr, vaddr)) 20862306a36Sopenharmony_ci#endif 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_cistatic __always_inline bool 21162306a36Sopenharmony_ciarch___test_and_set_bit(unsigned long nr, volatile unsigned long *addr) 21262306a36Sopenharmony_ci{ 21362306a36Sopenharmony_ci return test_and_set_bit(nr, addr); 21462306a36Sopenharmony_ci} 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_cistatic inline int bclr_reg_test_and_clear_bit(int nr, 21762306a36Sopenharmony_ci volatile unsigned long *vaddr) 21862306a36Sopenharmony_ci{ 21962306a36Sopenharmony_ci char *p = (char *)vaddr + (nr ^ 31) / 8; 22062306a36Sopenharmony_ci char retval; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci __asm__ __volatile__ ("bclr %2,(%1); sne %0" 22362306a36Sopenharmony_ci : "=d" (retval) 22462306a36Sopenharmony_ci : "a" (p), "di" (nr & 7) 22562306a36Sopenharmony_ci : "memory"); 22662306a36Sopenharmony_ci return retval; 22762306a36Sopenharmony_ci} 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_cistatic inline int bclr_mem_test_and_clear_bit(int nr, 23062306a36Sopenharmony_ci volatile unsigned long *vaddr) 23162306a36Sopenharmony_ci{ 23262306a36Sopenharmony_ci char *p = (char *)vaddr + (nr ^ 31) / 8; 23362306a36Sopenharmony_ci char retval; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci __asm__ __volatile__ ("bclr %2,%1; sne %0" 23662306a36Sopenharmony_ci : "=d" (retval), "+m" (*p) 23762306a36Sopenharmony_ci : "di" (nr & 7)); 23862306a36Sopenharmony_ci return retval; 23962306a36Sopenharmony_ci} 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_cistatic inline int bfclr_mem_test_and_clear_bit(int nr, 24262306a36Sopenharmony_ci volatile unsigned long *vaddr) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci char retval; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci __asm__ __volatile__ ("bfclr %2{%1:#1}; sne %0" 24762306a36Sopenharmony_ci : "=d" (retval) 24862306a36Sopenharmony_ci : "d" (nr ^ 31), "o" (*vaddr) 24962306a36Sopenharmony_ci : "memory"); 25062306a36Sopenharmony_ci return retval; 25162306a36Sopenharmony_ci} 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci#if defined(CONFIG_COLDFIRE) 25462306a36Sopenharmony_ci#define test_and_clear_bit(nr, vaddr) bclr_reg_test_and_clear_bit(nr, vaddr) 25562306a36Sopenharmony_ci#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS) 25662306a36Sopenharmony_ci#define test_and_clear_bit(nr, vaddr) bclr_mem_test_and_clear_bit(nr, vaddr) 25762306a36Sopenharmony_ci#else 25862306a36Sopenharmony_ci#define test_and_clear_bit(nr, vaddr) (__builtin_constant_p(nr) ? \ 25962306a36Sopenharmony_ci bclr_mem_test_and_clear_bit(nr, vaddr) : \ 26062306a36Sopenharmony_ci bfclr_mem_test_and_clear_bit(nr, vaddr)) 26162306a36Sopenharmony_ci#endif 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_cistatic __always_inline bool 26462306a36Sopenharmony_ciarch___test_and_clear_bit(unsigned long nr, volatile unsigned long *addr) 26562306a36Sopenharmony_ci{ 26662306a36Sopenharmony_ci return test_and_clear_bit(nr, addr); 26762306a36Sopenharmony_ci} 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_cistatic inline int bchg_reg_test_and_change_bit(int nr, 27062306a36Sopenharmony_ci volatile unsigned long *vaddr) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci char *p = (char *)vaddr + (nr ^ 31) / 8; 27362306a36Sopenharmony_ci char retval; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci __asm__ __volatile__ ("bchg %2,(%1); sne %0" 27662306a36Sopenharmony_ci : "=d" (retval) 27762306a36Sopenharmony_ci : "a" (p), "di" (nr & 7) 27862306a36Sopenharmony_ci : "memory"); 27962306a36Sopenharmony_ci return retval; 28062306a36Sopenharmony_ci} 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_cistatic inline int bchg_mem_test_and_change_bit(int nr, 28362306a36Sopenharmony_ci volatile unsigned long *vaddr) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci char *p = (char *)vaddr + (nr ^ 31) / 8; 28662306a36Sopenharmony_ci char retval; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci __asm__ __volatile__ ("bchg %2,%1; sne %0" 28962306a36Sopenharmony_ci : "=d" (retval), "+m" (*p) 29062306a36Sopenharmony_ci : "di" (nr & 7)); 29162306a36Sopenharmony_ci return retval; 29262306a36Sopenharmony_ci} 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_cistatic inline int bfchg_mem_test_and_change_bit(int nr, 29562306a36Sopenharmony_ci volatile unsigned long *vaddr) 29662306a36Sopenharmony_ci{ 29762306a36Sopenharmony_ci char retval; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci __asm__ __volatile__ ("bfchg %2{%1:#1}; sne %0" 30062306a36Sopenharmony_ci : "=d" (retval) 30162306a36Sopenharmony_ci : "d" (nr ^ 31), "o" (*vaddr) 30262306a36Sopenharmony_ci : "memory"); 30362306a36Sopenharmony_ci return retval; 30462306a36Sopenharmony_ci} 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci#if defined(CONFIG_COLDFIRE) 30762306a36Sopenharmony_ci#define test_and_change_bit(nr, vaddr) bchg_reg_test_and_change_bit(nr, vaddr) 30862306a36Sopenharmony_ci#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS) 30962306a36Sopenharmony_ci#define test_and_change_bit(nr, vaddr) bchg_mem_test_and_change_bit(nr, vaddr) 31062306a36Sopenharmony_ci#else 31162306a36Sopenharmony_ci#define test_and_change_bit(nr, vaddr) (__builtin_constant_p(nr) ? \ 31262306a36Sopenharmony_ci bchg_mem_test_and_change_bit(nr, vaddr) : \ 31362306a36Sopenharmony_ci bfchg_mem_test_and_change_bit(nr, vaddr)) 31462306a36Sopenharmony_ci#endif 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_cistatic __always_inline bool 31762306a36Sopenharmony_ciarch___test_and_change_bit(unsigned long nr, volatile unsigned long *addr) 31862306a36Sopenharmony_ci{ 31962306a36Sopenharmony_ci return test_and_change_bit(nr, addr); 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci/* 32362306a36Sopenharmony_ci * The true 68020 and more advanced processors support the "bfffo" 32462306a36Sopenharmony_ci * instruction for finding bits. ColdFire and simple 68000 parts 32562306a36Sopenharmony_ci * (including CPU32) do not support this. They simply use the generic 32662306a36Sopenharmony_ci * functions. 32762306a36Sopenharmony_ci */ 32862306a36Sopenharmony_ci#if defined(CONFIG_CPU_HAS_NO_BITFIELDS) 32962306a36Sopenharmony_ci#include <asm-generic/bitops/ffz.h> 33062306a36Sopenharmony_ci#else 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_cistatic inline int find_first_zero_bit(const unsigned long *vaddr, 33362306a36Sopenharmony_ci unsigned size) 33462306a36Sopenharmony_ci{ 33562306a36Sopenharmony_ci const unsigned long *p = vaddr; 33662306a36Sopenharmony_ci int res = 32; 33762306a36Sopenharmony_ci unsigned int words; 33862306a36Sopenharmony_ci unsigned long num; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci if (!size) 34162306a36Sopenharmony_ci return 0; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci words = (size + 31) >> 5; 34462306a36Sopenharmony_ci while (!(num = ~*p++)) { 34562306a36Sopenharmony_ci if (!--words) 34662306a36Sopenharmony_ci goto out; 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci __asm__ __volatile__ ("bfffo %1{#0,#0},%0" 35062306a36Sopenharmony_ci : "=d" (res) : "d" (num & -num)); 35162306a36Sopenharmony_ci res ^= 31; 35262306a36Sopenharmony_ciout: 35362306a36Sopenharmony_ci res += ((long)p - (long)vaddr - 4) * 8; 35462306a36Sopenharmony_ci return res < size ? res : size; 35562306a36Sopenharmony_ci} 35662306a36Sopenharmony_ci#define find_first_zero_bit find_first_zero_bit 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_cistatic inline int find_next_zero_bit(const unsigned long *vaddr, int size, 35962306a36Sopenharmony_ci int offset) 36062306a36Sopenharmony_ci{ 36162306a36Sopenharmony_ci const unsigned long *p = vaddr + (offset >> 5); 36262306a36Sopenharmony_ci int bit = offset & 31UL, res; 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci if (offset >= size) 36562306a36Sopenharmony_ci return size; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci if (bit) { 36862306a36Sopenharmony_ci unsigned long num = ~*p++ & (~0UL << bit); 36962306a36Sopenharmony_ci offset -= bit; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci /* Look for zero in first longword */ 37262306a36Sopenharmony_ci __asm__ __volatile__ ("bfffo %1{#0,#0},%0" 37362306a36Sopenharmony_ci : "=d" (res) : "d" (num & -num)); 37462306a36Sopenharmony_ci if (res < 32) { 37562306a36Sopenharmony_ci offset += res ^ 31; 37662306a36Sopenharmony_ci return offset < size ? offset : size; 37762306a36Sopenharmony_ci } 37862306a36Sopenharmony_ci offset += 32; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci if (offset >= size) 38162306a36Sopenharmony_ci return size; 38262306a36Sopenharmony_ci } 38362306a36Sopenharmony_ci /* No zero yet, search remaining full bytes for a zero */ 38462306a36Sopenharmony_ci return offset + find_first_zero_bit(p, size - offset); 38562306a36Sopenharmony_ci} 38662306a36Sopenharmony_ci#define find_next_zero_bit find_next_zero_bit 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_cistatic inline int find_first_bit(const unsigned long *vaddr, unsigned size) 38962306a36Sopenharmony_ci{ 39062306a36Sopenharmony_ci const unsigned long *p = vaddr; 39162306a36Sopenharmony_ci int res = 32; 39262306a36Sopenharmony_ci unsigned int words; 39362306a36Sopenharmony_ci unsigned long num; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci if (!size) 39662306a36Sopenharmony_ci return 0; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci words = (size + 31) >> 5; 39962306a36Sopenharmony_ci while (!(num = *p++)) { 40062306a36Sopenharmony_ci if (!--words) 40162306a36Sopenharmony_ci goto out; 40262306a36Sopenharmony_ci } 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci __asm__ __volatile__ ("bfffo %1{#0,#0},%0" 40562306a36Sopenharmony_ci : "=d" (res) : "d" (num & -num)); 40662306a36Sopenharmony_ci res ^= 31; 40762306a36Sopenharmony_ciout: 40862306a36Sopenharmony_ci res += ((long)p - (long)vaddr - 4) * 8; 40962306a36Sopenharmony_ci return res < size ? res : size; 41062306a36Sopenharmony_ci} 41162306a36Sopenharmony_ci#define find_first_bit find_first_bit 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_cistatic inline int find_next_bit(const unsigned long *vaddr, int size, 41462306a36Sopenharmony_ci int offset) 41562306a36Sopenharmony_ci{ 41662306a36Sopenharmony_ci const unsigned long *p = vaddr + (offset >> 5); 41762306a36Sopenharmony_ci int bit = offset & 31UL, res; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci if (offset >= size) 42062306a36Sopenharmony_ci return size; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci if (bit) { 42362306a36Sopenharmony_ci unsigned long num = *p++ & (~0UL << bit); 42462306a36Sopenharmony_ci offset -= bit; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci /* Look for one in first longword */ 42762306a36Sopenharmony_ci __asm__ __volatile__ ("bfffo %1{#0,#0},%0" 42862306a36Sopenharmony_ci : "=d" (res) : "d" (num & -num)); 42962306a36Sopenharmony_ci if (res < 32) { 43062306a36Sopenharmony_ci offset += res ^ 31; 43162306a36Sopenharmony_ci return offset < size ? offset : size; 43262306a36Sopenharmony_ci } 43362306a36Sopenharmony_ci offset += 32; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci if (offset >= size) 43662306a36Sopenharmony_ci return size; 43762306a36Sopenharmony_ci } 43862306a36Sopenharmony_ci /* No one yet, search remaining full bytes for a one */ 43962306a36Sopenharmony_ci return offset + find_first_bit(p, size - offset); 44062306a36Sopenharmony_ci} 44162306a36Sopenharmony_ci#define find_next_bit find_next_bit 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci/* 44462306a36Sopenharmony_ci * ffz = Find First Zero in word. Undefined if no zero exists, 44562306a36Sopenharmony_ci * so code should check against ~0UL first.. 44662306a36Sopenharmony_ci */ 44762306a36Sopenharmony_cistatic inline unsigned long ffz(unsigned long word) 44862306a36Sopenharmony_ci{ 44962306a36Sopenharmony_ci int res; 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci __asm__ __volatile__ ("bfffo %1{#0,#0},%0" 45262306a36Sopenharmony_ci : "=d" (res) : "d" (~word & -~word)); 45362306a36Sopenharmony_ci return res ^ 31; 45462306a36Sopenharmony_ci} 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci#endif 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci#ifdef __KERNEL__ 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci#if defined(CONFIG_CPU_HAS_NO_BITFIELDS) 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci/* 46362306a36Sopenharmony_ci * The newer ColdFire family members support a "bitrev" instruction 46462306a36Sopenharmony_ci * and we can use that to implement a fast ffs. Older Coldfire parts, 46562306a36Sopenharmony_ci * and normal 68000 parts don't have anything special, so we use the 46662306a36Sopenharmony_ci * generic functions for those. 46762306a36Sopenharmony_ci */ 46862306a36Sopenharmony_ci#if (defined(__mcfisaaplus__) || defined(__mcfisac__)) && \ 46962306a36Sopenharmony_ci !defined(CONFIG_M68000) 47062306a36Sopenharmony_cistatic inline unsigned long __ffs(unsigned long x) 47162306a36Sopenharmony_ci{ 47262306a36Sopenharmony_ci __asm__ __volatile__ ("bitrev %0; ff1 %0" 47362306a36Sopenharmony_ci : "=d" (x) 47462306a36Sopenharmony_ci : "0" (x)); 47562306a36Sopenharmony_ci return x; 47662306a36Sopenharmony_ci} 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_cistatic inline int ffs(int x) 47962306a36Sopenharmony_ci{ 48062306a36Sopenharmony_ci if (!x) 48162306a36Sopenharmony_ci return 0; 48262306a36Sopenharmony_ci return __ffs(x) + 1; 48362306a36Sopenharmony_ci} 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci#else 48662306a36Sopenharmony_ci#include <asm-generic/bitops/ffs.h> 48762306a36Sopenharmony_ci#include <asm-generic/bitops/__ffs.h> 48862306a36Sopenharmony_ci#endif 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci#include <asm-generic/bitops/fls.h> 49162306a36Sopenharmony_ci#include <asm-generic/bitops/__fls.h> 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci#else 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci/* 49662306a36Sopenharmony_ci * ffs: find first bit set. This is defined the same way as 49762306a36Sopenharmony_ci * the libc and compiler builtin ffs routines, therefore 49862306a36Sopenharmony_ci * differs in spirit from the above ffz (man ffs). 49962306a36Sopenharmony_ci */ 50062306a36Sopenharmony_cistatic inline int ffs(int x) 50162306a36Sopenharmony_ci{ 50262306a36Sopenharmony_ci int cnt; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci __asm__ ("bfffo %1{#0:#0},%0" 50562306a36Sopenharmony_ci : "=d" (cnt) 50662306a36Sopenharmony_ci : "dm" (x & -x)); 50762306a36Sopenharmony_ci return 32 - cnt; 50862306a36Sopenharmony_ci} 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_cistatic inline unsigned long __ffs(unsigned long x) 51162306a36Sopenharmony_ci{ 51262306a36Sopenharmony_ci return ffs(x) - 1; 51362306a36Sopenharmony_ci} 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci/* 51662306a36Sopenharmony_ci * fls: find last bit set. 51762306a36Sopenharmony_ci */ 51862306a36Sopenharmony_cistatic inline int fls(unsigned int x) 51962306a36Sopenharmony_ci{ 52062306a36Sopenharmony_ci int cnt; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci __asm__ ("bfffo %1{#0,#0},%0" 52362306a36Sopenharmony_ci : "=d" (cnt) 52462306a36Sopenharmony_ci : "dm" (x)); 52562306a36Sopenharmony_ci return 32 - cnt; 52662306a36Sopenharmony_ci} 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_cistatic inline unsigned long __fls(unsigned long x) 52962306a36Sopenharmony_ci{ 53062306a36Sopenharmony_ci return fls(x) - 1; 53162306a36Sopenharmony_ci} 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci#endif 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci/* Simple test-and-set bit locks */ 53662306a36Sopenharmony_ci#define test_and_set_bit_lock test_and_set_bit 53762306a36Sopenharmony_ci#define clear_bit_unlock clear_bit 53862306a36Sopenharmony_ci#define __clear_bit_unlock clear_bit_unlock 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci#include <asm-generic/bitops/non-instrumented-non-atomic.h> 54162306a36Sopenharmony_ci#include <asm-generic/bitops/ext2-atomic.h> 54262306a36Sopenharmony_ci#include <asm-generic/bitops/fls64.h> 54362306a36Sopenharmony_ci#include <asm-generic/bitops/sched.h> 54462306a36Sopenharmony_ci#include <asm-generic/bitops/hweight.h> 54562306a36Sopenharmony_ci#include <asm-generic/bitops/le.h> 54662306a36Sopenharmony_ci#endif /* __KERNEL__ */ 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci#endif /* _M68K_BITOPS_H */ 549