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 */ 27 static 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 42 static 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 */ 74 static 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 */ 85 static inline __attribute__ ((const)) unsigned long __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 */ 102 static 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 */ 117 static 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 */ 134 static inline __attribute__ ((const)) unsigned long __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 */ 144 static 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 */ 162 static 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 198