]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - include/asm-frv/bitops.h
forbid asm/bitops.h direct inclusion
[linux-2.6.git] / include / asm-frv / bitops.h
index 980ae1b0cd285a5578075b0d6e82866f5f7ea047..e29de7131b79dcca7250aad73b3d603fb1f53458 100644 (file)
 
 #ifdef __KERNEL__
 
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
 #include <asm-generic/bitops/ffz.h>
 
 /*
@@ -157,25 +161,152 @@ static inline int __test_bit(int nr, const volatile void * addr)
  __constant_test_bit((nr),(addr)) : \
  __test_bit((nr),(addr)))
 
-#include <asm-generic/bitops/ffs.h>
-#include <asm-generic/bitops/__ffs.h>
 #include <asm-generic/bitops/find.h>
 
-/*
- * fls: find last bit set.
+/**
+ * fls - find last bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as ffs:
+ * - return 32..1 to indicate bit 31..0 most significant bit set
+ * - return 0 to indicate no bits set
  */
 #define fls(x)                                         \
 ({                                                     \
        int bit;                                        \
                                                        \
-       asm("scan %1,gr0,%0" : "=r"(bit) : "r"(x));     \
+       asm("   subcc   %1,gr0,gr0,icc0         \n"     \
+           "   ckne    icc0,cc4                \n"     \
+           "   cscan.p %1,gr0,%0       ,cc4,#1 \n"     \
+           "   csub    %0,%0,%0        ,cc4,#0 \n"     \
+           "   csub    %2,%0,%0        ,cc4,#1 \n"     \
+           : "=&r"(bit)                                \
+           : "r"(x), "r"(32)                           \
+           : "icc0", "cc4"                             \
+           );                                          \
                                                        \
-       bit ? 33 - bit : bit;                           \
+       bit;                                            \
 })
 
-#include <asm-generic/bitops/fls64.h>
+/**
+ * fls64 - find last bit set in a 64-bit value
+ * @n: the value to search
+ *
+ * This is defined the same way as ffs:
+ * - return 64..1 to indicate bit 63..0 most significant bit set
+ * - return 0 to indicate no bits set
+ */
+static inline __attribute__((const))
+int fls64(u64 n)
+{
+       union {
+               u64 ll;
+               struct { u32 h, l; };
+       } _;
+       int bit, x, y;
+
+       _.ll = n;
+
+       asm("   subcc.p         %3,gr0,gr0,icc0         \n"
+           "   subcc           %4,gr0,gr0,icc1         \n"
+           "   ckne            icc0,cc4                \n"
+           "   ckne            icc1,cc5                \n"
+           "   norcr           cc4,cc5,cc6             \n"
+           "   csub.p          %0,%0,%0        ,cc6,1  \n"
+           "   orcr            cc5,cc4,cc4             \n"
+           "   andcr           cc4,cc5,cc4             \n"
+           "   cscan.p         %3,gr0,%0       ,cc4,0  \n"
+           "   setlos          #64,%1                  \n"
+           "   cscan.p         %4,gr0,%0       ,cc4,1  \n"
+           "   setlos          #32,%2                  \n"
+           "   csub.p          %1,%0,%0        ,cc4,0  \n"
+           "   csub            %2,%0,%0        ,cc4,1  \n"
+           : "=&r"(bit), "=r"(x), "=r"(y)
+           : "0r"(_.h), "r"(_.l)
+           : "icc0", "icc1", "cc4", "cc5", "cc6"
+           );
+       return bit;
+
+}
+
+/**
+ * ffs - find first bit set
+ * @x: the word to search
+ *
+ * - return 32..1 to indicate bit 31..0 most least significant bit set
+ * - return 0 to indicate no bits set
+ */
+static inline __attribute__((const))
+int ffs(int x)
+{
+       /* Note: (x & -x) gives us a mask that is the least significant
+        * (rightmost) 1-bit of the value in x.
+        */
+       return fls(x & -x);
+}
+
+/**
+ * __ffs - find first bit set
+ * @x: the word to search
+ *
+ * - return 31..0 to indicate bit 31..0 most least significant bit set
+ * - if no bits are set in x, the result is undefined
+ */
+static inline __attribute__((const))
+int __ffs(unsigned long x)
+{
+       int bit;
+       asm("scan %1,gr0,%0" : "=r"(bit) : "r"(x & -x));
+       return 31 - bit;
+}
+
+/*
+ * special slimline version of fls() for calculating ilog2_u32()
+ * - note: no protection against n == 0
+ */
+#define ARCH_HAS_ILOG2_U32
+static inline __attribute__((const))
+int __ilog2_u32(u32 n)
+{
+       int bit;
+       asm("scan %1,gr0,%0" : "=r"(bit) : "r"(n));
+       return 31 - bit;
+}
+
+/*
+ * special slimline version of fls64() for calculating ilog2_u64()
+ * - note: no protection against n == 0
+ */
+#define ARCH_HAS_ILOG2_U64
+static inline __attribute__((const))
+int __ilog2_u64(u64 n)
+{
+       union {
+               u64 ll;
+               struct { u32 h, l; };
+       } _;
+       int bit, x, y;
+
+       _.ll = n;
+
+       asm("   subcc           %3,gr0,gr0,icc0         \n"
+           "   ckeq            icc0,cc4                \n"
+           "   cscan.p         %3,gr0,%0       ,cc4,0  \n"
+           "   setlos          #63,%1                  \n"
+           "   cscan.p         %4,gr0,%0       ,cc4,1  \n"
+           "   setlos          #31,%2                  \n"
+           "   csub.p          %1,%0,%0        ,cc4,0  \n"
+           "   csub            %2,%0,%0        ,cc4,1  \n"
+           : "=&r"(bit), "=r"(x), "=r"(y)
+           : "0r"(_.h), "r"(_.l)
+           : "icc0", "cc4"
+           );
+       return bit;
+}
+
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/ext2-non-atomic.h>