diff options
author | Chris Zankel <chris@zankel.net> | 2007-05-31 20:41:14 -0400 |
---|---|---|
committer | Chris Zankel <chris@zankel.net> | 2007-05-31 20:41:14 -0400 |
commit | ef6051a90e2ad1af636e99d1d4603fdcf2adfcbe (patch) | |
tree | ac64477663d0163161f3646cda4e5dd0c1e21893 | |
parent | 3f0a6766e0cc5a577805732e5adb50a585c58175 (diff) |
[XTENSA] fix bit operations in bitops.h
A macro used internally in the bitops.h file to identify the number of
leading zeros (__cntlz) was implemented incorrectly for Xtensa processors
that don't provide the 'nsa/nsau' instructions. As a result, the dependent
functions and macros (ffs, ffz, fls) were broken.
Signed-off-by: Chris Zankel <chris@zankel.net>
-rw-r--r-- | include/asm-xtensa/bitops.h | 60 |
1 files changed, 26 insertions, 34 deletions
diff --git a/include/asm-xtensa/bitops.h b/include/asm-xtensa/bitops.h index d815649617aa..96303dff3ee4 100644 --- a/include/asm-xtensa/bitops.h +++ b/include/asm-xtensa/bitops.h | |||
@@ -7,7 +7,7 @@ | |||
7 | * License. See the file "COPYING" in the main directory of this archive | 7 | * License. See the file "COPYING" in the main directory of this archive |
8 | * for more details. | 8 | * for more details. |
9 | * | 9 | * |
10 | * Copyright (C) 2001 - 2005 Tensilica Inc. | 10 | * Copyright (C) 2001 - 2007 Tensilica Inc. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #ifndef _XTENSA_BITOPS_H | 13 | #ifndef _XTENSA_BITOPS_H |
@@ -31,64 +31,44 @@ | |||
31 | 31 | ||
32 | #if XCHAL_HAVE_NSA | 32 | #if XCHAL_HAVE_NSA |
33 | 33 | ||
34 | static __inline__ int __cntlz (unsigned long x) | 34 | static inline unsigned long __cntlz (unsigned long x) |
35 | { | 35 | { |
36 | int lz; | 36 | int lz; |
37 | asm ("nsau %0, %1" : "=r" (lz) : "r" (x)); | 37 | asm ("nsau %0, %1" : "=r" (lz) : "r" (x)); |
38 | return 31 - lz; | 38 | return lz; |
39 | } | 39 | } |
40 | 40 | ||
41 | #else | ||
42 | |||
43 | static __inline__ int __cntlz (unsigned long x) | ||
44 | { | ||
45 | unsigned long sum, x1, x2, x4, x8, x16; | ||
46 | x1 = x & 0xAAAAAAAA; | ||
47 | x2 = x & 0xCCCCCCCC; | ||
48 | x4 = x & 0xF0F0F0F0; | ||
49 | x8 = x & 0xFF00FF00; | ||
50 | x16 = x & 0xFFFF0000; | ||
51 | sum = x2 ? 2 : 0; | ||
52 | sum += (x16 != 0) * 16; | ||
53 | sum += (x8 != 0) * 8; | ||
54 | sum += (x4 != 0) * 4; | ||
55 | sum += (x1 != 0); | ||
56 | |||
57 | return sum; | ||
58 | } | ||
59 | |||
60 | #endif | ||
61 | |||
62 | /* | 41 | /* |
63 | * ffz: Find first zero in word. Undefined if no zero exists. | 42 | * ffz: Find first zero in word. Undefined if no zero exists. |
64 | * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). | 43 | * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). |
65 | */ | 44 | */ |
66 | 45 | ||
67 | static __inline__ int ffz(unsigned long x) | 46 | static inline int ffz(unsigned long x) |
68 | { | 47 | { |
69 | if ((x = ~x) == 0) | 48 | return 31 - __cntlz(~x & -~x); |
70 | return 32; | ||
71 | return __cntlz(x & -x); | ||
72 | } | 49 | } |
73 | 50 | ||
74 | /* | 51 | /* |
75 | * __ffs: Find first bit set in word. Return 0 for bit 0 | 52 | * __ffs: Find first bit set in word. Return 0 for bit 0 |
76 | */ | 53 | */ |
77 | 54 | ||
78 | static __inline__ int __ffs(unsigned long x) | 55 | static inline int __ffs(unsigned long x) |
79 | { | 56 | { |
80 | return __cntlz(x & -x); | 57 | return 31 - __cntlz(x & -x); |
81 | } | 58 | } |
82 | 59 | ||
60 | |||
61 | #ifdef __KERNEL__ | ||
62 | |||
83 | /* | 63 | /* |
84 | * ffs: Find first bit set in word. This is defined the same way as | 64 | * ffs: Find first bit set in word. This is defined the same way as |
85 | * the libc and compiler builtin ffs routines, therefore | 65 | * the libc and compiler builtin ffs routines, therefore |
86 | * differs in spirit from the above ffz (man ffs). | 66 | * differs in spirit from the above ffz (man ffs). |
87 | */ | 67 | */ |
88 | 68 | ||
89 | static __inline__ int ffs(unsigned long x) | 69 | static inline int ffs(unsigned long x) |
90 | { | 70 | { |
91 | return __cntlz(x & -x) + 1; | 71 | return 32 - __cntlz(x & -x); |
92 | } | 72 | } |
93 | 73 | ||
94 | /* | 74 | /* |
@@ -96,10 +76,22 @@ static __inline__ int ffs(unsigned long x) | |||
96 | * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. | 76 | * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. |
97 | */ | 77 | */ |
98 | 78 | ||
99 | static __inline__ int fls (unsigned int x) | 79 | static inline int fls (unsigned int x) |
100 | { | 80 | { |
101 | return __cntlz(x); | 81 | return 32 - __cntlz(x); |
102 | } | 82 | } |
83 | |||
84 | #else | ||
85 | |||
86 | /* Use the generic implementation if we don't have the nsa/nsau instructions. */ | ||
87 | |||
88 | # include <asm-generic/bitops/ffs.h> | ||
89 | # include <asm-generic/bitops/__ffs.h> | ||
90 | # include <asm-generic/bitops/ffz.h> | ||
91 | # include <asm-generic/bitops/fls.h> | ||
92 | |||
93 | #endif | ||
94 | |||
103 | #include <asm-generic/bitops/fls64.h> | 95 | #include <asm-generic/bitops/fls64.h> |
104 | #include <asm-generic/bitops/find.h> | 96 | #include <asm-generic/bitops/find.h> |
105 | #include <asm-generic/bitops/ext2-non-atomic.h> | 97 | #include <asm-generic/bitops/ext2-non-atomic.h> |