Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
0004  */
0005 
0006 #ifndef _ASM_BITOPS_H
0007 #define _ASM_BITOPS_H
0008 
0009 #ifndef _LINUX_BITOPS_H
0010 #error only <linux/bitops.h> can be included directly
0011 #endif
0012 
0013 #ifndef __ASSEMBLY__
0014 
0015 #include <linux/types.h>
0016 #include <linux/compiler.h>
0017 
0018 #ifdef CONFIG_ISA_ARCOMPACT
0019 
0020 /*
0021  * Count the number of zeros, starting from MSB
0022  * Helper for fls( ) friends
0023  * This is a pure count, so (1-32) or (0-31) doesn't apply
0024  * It could be 0 to 32, based on num of 0's in there
0025  * clz(0x8000_0000) = 0, clz(0xFFFF_FFFF)=0, clz(0) = 32, clz(1) = 31
0026  */
0027 static inline __attribute__ ((const)) int clz(unsigned int x)
0028 {
0029     unsigned int res;
0030 
0031     __asm__ __volatile__(
0032     "   norm.f  %0, %1      \n"
0033     "   mov.n   %0, 0       \n"
0034     "   add.p   %0, %0, 1   \n"
0035     : "=r"(res)
0036     : "r"(x)
0037     : "cc");
0038 
0039     return res;
0040 }
0041 
0042 static inline int constant_fls(unsigned int x)
0043 {
0044     int r = 32;
0045 
0046     if (!x)
0047         return 0;
0048     if (!(x & 0xffff0000u)) {
0049         x <<= 16;
0050         r -= 16;
0051     }
0052     if (!(x & 0xff000000u)) {
0053         x <<= 8;
0054         r -= 8;
0055     }
0056     if (!(x & 0xf0000000u)) {
0057         x <<= 4;
0058         r -= 4;
0059     }
0060     if (!(x & 0xc0000000u)) {
0061         x <<= 2;
0062         r -= 2;
0063     }
0064     if (!(x & 0x80000000u))
0065         r -= 1;
0066     return r;
0067 }
0068 
0069 /*
0070  * fls = Find Last Set in word
0071  * @result: [1-32]
0072  * fls(1) = 1, fls(0x80000000) = 32, fls(0) = 0
0073  */
0074 static inline __attribute__ ((const)) int fls(unsigned int x)
0075 {
0076     if (__builtin_constant_p(x))
0077            return constant_fls(x);
0078 
0079     return 32 - clz(x);
0080 }
0081 
0082 /*
0083  * __fls: Similar to fls, but zero based (0-31)
0084  */
0085 static inline __attribute__ ((const)) int __fls(unsigned long x)
0086 {
0087     if (!x)
0088         return 0;
0089     else
0090         return fls(x) - 1;
0091 }
0092 
0093 /*
0094  * ffs = Find First Set in word (LSB to MSB)
0095  * @result: [1-32], 0 if all 0's
0096  */
0097 #define ffs(x)  ({ unsigned long __t = (x); fls(__t & -__t); })
0098 
0099 /*
0100  * __ffs: Similar to ffs, but zero based (0-31)
0101  */
0102 static inline __attribute__ ((const)) unsigned long __ffs(unsigned long word)
0103 {
0104     if (!word)
0105         return word;
0106 
0107     return ffs(word) - 1;
0108 }
0109 
0110 #else   /* CONFIG_ISA_ARCV2 */
0111 
0112 /*
0113  * fls = Find Last Set in word
0114  * @result: [1-32]
0115  * fls(1) = 1, fls(0x80000000) = 32, fls(0) = 0
0116  */
0117 static inline __attribute__ ((const)) int fls(unsigned int x)
0118 {
0119     int n;
0120 
0121     asm volatile(
0122     "   fls.f   %0, %1      \n"  /* 0:31; 0(Z) if src 0 */
0123     "   add.nz  %0, %0, 1   \n"  /* 0:31 -> 1:32 */
0124     : "=r"(n)   /* Early clobber not needed */
0125     : "r"(x)
0126     : "cc");
0127 
0128     return n;
0129 }
0130 
0131 /*
0132  * __fls: Similar to fls, but zero based (0-31). Also 0 if no bit set
0133  */
0134 static inline __attribute__ ((const)) int __fls(unsigned long x)
0135 {
0136     /* FLS insn has exactly same semantics as the API */
0137     return  __builtin_arc_fls(x);
0138 }
0139 
0140 /*
0141  * ffs = Find First Set in word (LSB to MSB)
0142  * @result: [1-32], 0 if all 0's
0143  */
0144 static inline __attribute__ ((const)) int ffs(unsigned int x)
0145 {
0146     int n;
0147 
0148     asm volatile(
0149     "   ffs.f   %0, %1      \n"  /* 0:31; 31(Z) if src 0 */
0150     "   add.nz  %0, %0, 1   \n"  /* 0:31 -> 1:32 */
0151     "   mov.z   %0, 0       \n"  /* 31(Z)-> 0 */
0152     : "=r"(n)   /* Early clobber not needed */
0153     : "r"(x)
0154     : "cc");
0155 
0156     return n;
0157 }
0158 
0159 /*
0160  * __ffs: Similar to ffs, but zero based (0-31)
0161  */
0162 static inline __attribute__ ((const)) unsigned long __ffs(unsigned long x)
0163 {
0164     unsigned long n;
0165 
0166     asm volatile(
0167     "   ffs.f   %0, %1      \n"  /* 0:31; 31(Z) if src 0 */
0168     "   mov.z   %0, 0       \n"  /* 31(Z)-> 0 */
0169     : "=r"(n)
0170     : "r"(x)
0171     : "cc");
0172 
0173     return n;
0174 
0175 }
0176 
0177 #endif  /* CONFIG_ISA_ARCOMPACT */
0178 
0179 /*
0180  * ffz = Find First Zero in word.
0181  * @return:[0-31], 32 if all 1's
0182  */
0183 #define ffz(x)  __ffs(~(x))
0184 
0185 #include <asm-generic/bitops/hweight.h>
0186 #include <asm-generic/bitops/fls64.h>
0187 #include <asm-generic/bitops/sched.h>
0188 #include <asm-generic/bitops/lock.h>
0189 #include <asm-generic/bitops/atomic.h>
0190 #include <asm-generic/bitops/non-atomic.h>
0191 
0192 #include <asm-generic/bitops/le.h>
0193 #include <asm-generic/bitops/ext2-atomic-setbit.h>
0194 
0195 #endif /* !__ASSEMBLY__ */
0196 
0197 #endif