bitops.h (3762B)
1/* SPDX-License-Identifier: GPL-2.0-only */ 2/* 3 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) 4 */ 5 6#ifndef _ASM_BITOPS_H 7#define _ASM_BITOPS_H 8 9#ifndef _LINUX_BITOPS_H 10#error only <linux/bitops.h> can be included directly 11#endif 12 13#ifndef __ASSEMBLY__ 14 15#include <linux/types.h> 16#include <linux/compiler.h> 17 18#ifdef CONFIG_ISA_ARCOMPACT 19 20/* 21 * Count the number of zeros, starting from MSB 22 * Helper for fls( ) friends 23 * This is a pure count, so (1-32) or (0-31) doesn't apply 24 * It could be 0 to 32, based on num of 0's in there 25 * clz(0x8000_0000) = 0, clz(0xFFFF_FFFF)=0, clz(0) = 32, clz(1) = 31 26 */ 27static inline __attribute__ ((const)) int clz(unsigned int x) 28{ 29 unsigned int res; 30 31 __asm__ __volatile__( 32 " norm.f %0, %1 \n" 33 " mov.n %0, 0 \n" 34 " add.p %0, %0, 1 \n" 35 : "=r"(res) 36 : "r"(x) 37 : "cc"); 38 39 return res; 40} 41 42static inline int constant_fls(unsigned int x) 43{ 44 int r = 32; 45 46 if (!x) 47 return 0; 48 if (!(x & 0xffff0000u)) { 49 x <<= 16; 50 r -= 16; 51 } 52 if (!(x & 0xff000000u)) { 53 x <<= 8; 54 r -= 8; 55 } 56 if (!(x & 0xf0000000u)) { 57 x <<= 4; 58 r -= 4; 59 } 60 if (!(x & 0xc0000000u)) { 61 x <<= 2; 62 r -= 2; 63 } 64 if (!(x & 0x80000000u)) 65 r -= 1; 66 return r; 67} 68 69/* 70 * fls = Find Last Set in word 71 * @result: [1-32] 72 * fls(1) = 1, fls(0x80000000) = 32, fls(0) = 0 73 */ 74static inline __attribute__ ((const)) int fls(unsigned int x) 75{ 76 if (__builtin_constant_p(x)) 77 return constant_fls(x); 78 79 return 32 - clz(x); 80} 81 82/* 83 * __fls: Similar to fls, but zero based (0-31) 84 */ 85static inline __attribute__ ((const)) int __fls(unsigned long x) 86{ 87 if (!x) 88 return 0; 89 else 90 return fls(x) - 1; 91} 92 93/* 94 * ffs = Find First Set in word (LSB to MSB) 95 * @result: [1-32], 0 if all 0's 96 */ 97#define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); }) 98 99/* 100 * __ffs: Similar to ffs, but zero based (0-31) 101 */ 102static inline __attribute__ ((const)) unsigned long __ffs(unsigned long word) 103{ 104 if (!word) 105 return word; 106 107 return ffs(word) - 1; 108} 109 110#else /* CONFIG_ISA_ARCV2 */ 111 112/* 113 * fls = Find Last Set in word 114 * @result: [1-32] 115 * fls(1) = 1, fls(0x80000000) = 32, fls(0) = 0 116 */ 117static inline __attribute__ ((const)) int fls(unsigned int x) 118{ 119 int n; 120 121 asm volatile( 122 " fls.f %0, %1 \n" /* 0:31; 0(Z) if src 0 */ 123 " add.nz %0, %0, 1 \n" /* 0:31 -> 1:32 */ 124 : "=r"(n) /* Early clobber not needed */ 125 : "r"(x) 126 : "cc"); 127 128 return n; 129} 130 131/* 132 * __fls: Similar to fls, but zero based (0-31). Also 0 if no bit set 133 */ 134static inline __attribute__ ((const)) int __fls(unsigned long x) 135{ 136 /* FLS insn has exactly same semantics as the API */ 137 return __builtin_arc_fls(x); 138} 139 140/* 141 * ffs = Find First Set in word (LSB to MSB) 142 * @result: [1-32], 0 if all 0's 143 */ 144static inline __attribute__ ((const)) int ffs(unsigned int x) 145{ 146 int n; 147 148 asm volatile( 149 " ffs.f %0, %1 \n" /* 0:31; 31(Z) if src 0 */ 150 " add.nz %0, %0, 1 \n" /* 0:31 -> 1:32 */ 151 " mov.z %0, 0 \n" /* 31(Z)-> 0 */ 152 : "=r"(n) /* Early clobber not needed */ 153 : "r"(x) 154 : "cc"); 155 156 return n; 157} 158 159/* 160 * __ffs: Similar to ffs, but zero based (0-31) 161 */ 162static inline __attribute__ ((const)) unsigned long __ffs(unsigned long x) 163{ 164 unsigned long n; 165 166 asm volatile( 167 " ffs.f %0, %1 \n" /* 0:31; 31(Z) if src 0 */ 168 " mov.z %0, 0 \n" /* 31(Z)-> 0 */ 169 : "=r"(n) 170 : "r"(x) 171 : "cc"); 172 173 return n; 174 175} 176 177#endif /* CONFIG_ISA_ARCOMPACT */ 178 179/* 180 * ffz = Find First Zero in word. 181 * @return:[0-31], 32 if all 1's 182 */ 183#define ffz(x) __ffs(~(x)) 184 185#include <asm-generic/bitops/hweight.h> 186#include <asm-generic/bitops/fls64.h> 187#include <asm-generic/bitops/sched.h> 188#include <asm-generic/bitops/lock.h> 189#include <asm-generic/bitops/atomic.h> 190#include <asm-generic/bitops/non-atomic.h> 191 192#include <asm-generic/bitops/le.h> 193#include <asm-generic/bitops/ext2-atomic-setbit.h> 194 195#endif /* !__ASSEMBLY__ */ 196 197#endif