diff options
author | David Howells <dhowells@redhat.com> | 2006-12-08 05:37:49 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-08 11:28:51 -0500 |
commit | f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8 (patch) | |
tree | 0aa5379150574374351fb92af7881a48dbfcf2ce /include/asm-frv | |
parent | b3d7ae5f47a58a9f7b152deeaf7daa1fc558a8f1 (diff) |
[PATCH] LOG2: Implement a general integer log2 facility in the kernel
This facility provides three entry points:
ilog2() Log base 2 of unsigned long
ilog2_u32() Log base 2 of u32
ilog2_u64() Log base 2 of u64
These facilities can either be used inside functions on dynamic data:
int do_something(long q)
{
...;
y = ilog2(x)
...;
}
Or can be used to statically initialise global variables with constant values:
unsigned n = ilog2(27);
When performing static initialisation, the compiler will report "error:
initializer element is not constant" if asked to take a log of zero or of
something not reducible to a constant. They treat negative numbers as
unsigned.
When not dealing with a constant, they fall back to using fls() which permits
them to use arch-specific log calculation instructions - such as BSR on
x86/x86_64 or SCAN on FRV - if available.
[akpm@osdl.org: MMC fix]
Signed-off-by: David Howells <dhowells@redhat.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: David Howells <dhowells@redhat.com>
Cc: Wojtek Kaniewski <wojtekka@toxygen.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'include/asm-frv')
-rw-r--r-- | include/asm-frv/bitops.h | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/include/asm-frv/bitops.h b/include/asm-frv/bitops.h index 1f70d47148bd..f8560edf59ff 100644 --- a/include/asm-frv/bitops.h +++ b/include/asm-frv/bitops.h | |||
@@ -256,6 +256,50 @@ int __ffs(unsigned long x) | |||
256 | return 31 - bit; | 256 | return 31 - bit; |
257 | } | 257 | } |
258 | 258 | ||
259 | /* | ||
260 | * special slimline version of fls() for calculating ilog2_u32() | ||
261 | * - note: no protection against n == 0 | ||
262 | */ | ||
263 | #define ARCH_HAS_ILOG2_U32 | ||
264 | static inline __attribute__((const)) | ||
265 | int __ilog2_u32(u32 n) | ||
266 | { | ||
267 | int bit; | ||
268 | asm("scan %1,gr0,%0" : "=r"(bit) : "r"(n)); | ||
269 | return 31 - bit; | ||
270 | } | ||
271 | |||
272 | /* | ||
273 | * special slimline version of fls64() for calculating ilog2_u64() | ||
274 | * - note: no protection against n == 0 | ||
275 | */ | ||
276 | #define ARCH_HAS_ILOG2_U64 | ||
277 | static inline __attribute__((const)) | ||
278 | int __ilog2_u64(u64 n) | ||
279 | { | ||
280 | union { | ||
281 | u64 ll; | ||
282 | struct { u32 h, l; }; | ||
283 | } _; | ||
284 | int bit, x, y; | ||
285 | |||
286 | _.ll = n; | ||
287 | |||
288 | asm(" subcc %3,gr0,gr0,icc0 \n" | ||
289 | " ckeq icc0,cc4 \n" | ||
290 | " cscan.p %3,gr0,%0 ,cc4,0 \n" | ||
291 | " setlos #63,%1 \n" | ||
292 | " cscan.p %4,gr0,%0 ,cc4,1 \n" | ||
293 | " setlos #31,%2 \n" | ||
294 | " csub.p %1,%0,%0 ,cc4,0 \n" | ||
295 | " csub %2,%0,%0 ,cc4,1 \n" | ||
296 | : "=&r"(bit), "=r"(x), "=r"(y) | ||
297 | : "0r"(_.h), "r"(_.l) | ||
298 | : "icc0", "cc4" | ||
299 | ); | ||
300 | return bit; | ||
301 | } | ||
302 | |||
259 | #include <asm-generic/bitops/sched.h> | 303 | #include <asm-generic/bitops/sched.h> |
260 | #include <asm-generic/bitops/hweight.h> | 304 | #include <asm-generic/bitops/hweight.h> |
261 | 305 | ||