summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2006-09-25 23:32:08 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-26 08:48:54 -0700
commita8ad27d03f17e6154c61e81d4a7028c56ca6390d (patch)
tree14d0367af1fafa359733b04326a95a4fe39557c5
parent92fc707208bb2e601c24b5ab65db37bcb361b658 (diff)
downloadlinux-a8ad27d03f17e6154c61e81d4a7028c56ca6390d.tar.bz2
[PATCH] FRV: Implement fls64()
Implement fls64() for FRV without recource to conditional jumps. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--include/asm-frv/bitops.h42
1 files changed, 41 insertions, 1 deletions
diff --git a/include/asm-frv/bitops.h b/include/asm-frv/bitops.h
index 97fb746f76c7..591eecc1f8cd 100644
--- a/include/asm-frv/bitops.h
+++ b/include/asm-frv/bitops.h
@@ -186,7 +186,47 @@ static inline int __test_bit(int nr, const volatile void * addr)
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;
+
+}
+
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>