Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
[linux-2.6.git] / arch / arm / lib / findbit.S
1 /*
2  *  linux/arch/arm/lib/findbit.S
3  *
4  *  Copyright (C) 1995-2000 Russell King
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * 16th March 2001 - John Ripley <jripley@sonicblue.com>
11  *   Fixed so that "size" is an exclusive not an inclusive quantity.
12  *   All users of these functions expect exclusive sizes, and may
13  *   also call with zero size.
14  * Reworked by rmk.
15  */
16 #include <linux/linkage.h>
17 #include <asm/assembler.h>
18                 .text
19
20 /*
21  * Purpose  : Find a 'zero' bit
22  * Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
23  */
24 ENTRY(_find_first_zero_bit_le)
25                 teq     r1, #0  
26                 beq     3f
27                 mov     r2, #0
28 1:
29  ARM(           ldrb    r3, [r0, r2, lsr #3]    )
30  THUMB(         lsr     r3, r2, #3              )
31  THUMB(         ldrb    r3, [r0, r3]            )
32                 eors    r3, r3, #0xff           @ invert bits
33                 bne     .L_found                @ any now set - found zero bit
34                 add     r2, r2, #8              @ next bit pointer
35 2:              cmp     r2, r1                  @ any more?
36                 blo     1b
37 3:              mov     r0, r1                  @ no free bits
38                 mov     pc, lr
39 ENDPROC(_find_first_zero_bit_le)
40
41 /*
42  * Purpose  : Find next 'zero' bit
43  * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
44  */
45 ENTRY(_find_next_zero_bit_le)
46                 teq     r1, #0
47                 beq     3b
48                 ands    ip, r2, #7
49                 beq     1b                      @ If new byte, goto old routine
50  ARM(           ldrb    r3, [r0, r2, lsr #3]    )
51  THUMB(         lsr     r3, r2, #3              )
52  THUMB(         ldrb    r3, [r0, r3]            )
53                 eor     r3, r3, #0xff           @ now looking for a 1 bit
54                 movs    r3, r3, lsr ip          @ shift off unused bits
55                 bne     .L_found
56                 orr     r2, r2, #7              @ if zero, then no bits here
57                 add     r2, r2, #1              @ align bit pointer
58                 b       2b                      @ loop for next bit
59 ENDPROC(_find_next_zero_bit_le)
60
61 /*
62  * Purpose  : Find a 'one' bit
63  * Prototype: int find_first_bit(const unsigned long *addr, unsigned int maxbit);
64  */
65 ENTRY(_find_first_bit_le)
66                 teq     r1, #0  
67                 beq     3f
68                 mov     r2, #0
69 1:
70  ARM(           ldrb    r3, [r0, r2, lsr #3]    )
71  THUMB(         lsr     r3, r2, #3              )
72  THUMB(         ldrb    r3, [r0, r3]            )
73                 movs    r3, r3
74                 bne     .L_found                @ any now set - found zero bit
75                 add     r2, r2, #8              @ next bit pointer
76 2:              cmp     r2, r1                  @ any more?
77                 blo     1b
78 3:              mov     r0, r1                  @ no free bits
79                 mov     pc, lr
80 ENDPROC(_find_first_bit_le)
81
82 /*
83  * Purpose  : Find next 'one' bit
84  * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
85  */
86 ENTRY(_find_next_bit_le)
87                 teq     r1, #0
88                 beq     3b
89                 ands    ip, r2, #7
90                 beq     1b                      @ If new byte, goto old routine
91  ARM(           ldrb    r3, [r0, r2, lsr #3]    )
92  THUMB(         lsr     r3, r2, #3              )
93  THUMB(         ldrb    r3, [r0, r3]            )
94                 movs    r3, r3, lsr ip          @ shift off unused bits
95                 bne     .L_found
96                 orr     r2, r2, #7              @ if zero, then no bits here
97                 add     r2, r2, #1              @ align bit pointer
98                 b       2b                      @ loop for next bit
99 ENDPROC(_find_next_bit_le)
100
101 #ifdef __ARMEB__
102
103 ENTRY(_find_first_zero_bit_be)
104                 teq     r1, #0
105                 beq     3f
106                 mov     r2, #0
107 1:              eor     r3, r2, #0x18           @ big endian byte ordering
108  ARM(           ldrb    r3, [r0, r3, lsr #3]    )
109  THUMB(         lsr     r3, #3                  )
110  THUMB(         ldrb    r3, [r0, r3]            )
111                 eors    r3, r3, #0xff           @ invert bits
112                 bne     .L_found                @ any now set - found zero bit
113                 add     r2, r2, #8              @ next bit pointer
114 2:              cmp     r2, r1                  @ any more?
115                 blo     1b
116 3:              mov     r0, r1                  @ no free bits
117                 mov     pc, lr
118 ENDPROC(_find_first_zero_bit_be)
119
120 ENTRY(_find_next_zero_bit_be)
121                 teq     r1, #0
122                 beq     3b
123                 ands    ip, r2, #7
124                 beq     1b                      @ If new byte, goto old routine
125                 eor     r3, r2, #0x18           @ big endian byte ordering
126  ARM(           ldrb    r3, [r0, r3, lsr #3]    )
127  THUMB(         lsr     r3, #3                  )
128  THUMB(         ldrb    r3, [r0, r3]            )
129                 eor     r3, r3, #0xff           @ now looking for a 1 bit
130                 movs    r3, r3, lsr ip          @ shift off unused bits
131                 bne     .L_found
132                 orr     r2, r2, #7              @ if zero, then no bits here
133                 add     r2, r2, #1              @ align bit pointer
134                 b       2b                      @ loop for next bit
135 ENDPROC(_find_next_zero_bit_be)
136
137 ENTRY(_find_first_bit_be)
138                 teq     r1, #0
139                 beq     3f
140                 mov     r2, #0
141 1:              eor     r3, r2, #0x18           @ big endian byte ordering
142  ARM(           ldrb    r3, [r0, r3, lsr #3]    )
143  THUMB(         lsr     r3, #3                  )
144  THUMB(         ldrb    r3, [r0, r3]            )
145                 movs    r3, r3
146                 bne     .L_found                @ any now set - found zero bit
147                 add     r2, r2, #8              @ next bit pointer
148 2:              cmp     r2, r1                  @ any more?
149                 blo     1b
150 3:              mov     r0, r1                  @ no free bits
151                 mov     pc, lr
152 ENDPROC(_find_first_bit_be)
153
154 ENTRY(_find_next_bit_be)
155                 teq     r1, #0
156                 beq     3b
157                 ands    ip, r2, #7
158                 beq     1b                      @ If new byte, goto old routine
159                 eor     r3, r2, #0x18           @ big endian byte ordering
160  ARM(           ldrb    r3, [r0, r3, lsr #3]    )
161  THUMB(         lsr     r3, #3                  )
162  THUMB(         ldrb    r3, [r0, r3]            )
163                 movs    r3, r3, lsr ip          @ shift off unused bits
164                 bne     .L_found
165                 orr     r2, r2, #7              @ if zero, then no bits here
166                 add     r2, r2, #1              @ align bit pointer
167                 b       2b                      @ loop for next bit
168 ENDPROC(_find_next_bit_be)
169
170 #endif
171
172 /*
173  * One or more bits in the LSB of r3 are assumed to be set.
174  */
175 .L_found:
176 #if __LINUX_ARM_ARCH__ >= 5
177                 rsb     r1, r3, #0
178                 and     r3, r3, r1
179                 clz     r3, r3
180                 rsb     r3, r3, #31
181                 add     r0, r2, r3
182 #else
183                 tst     r3, #0x0f
184                 addeq   r2, r2, #4
185                 movne   r3, r3, lsl #4
186                 tst     r3, #0x30
187                 addeq   r2, r2, #2
188                 movne   r3, r3, lsl #2
189                 tst     r3, #0x40
190                 addeq   r2, r2, #1
191                 mov     r0, r2
192 #endif
193                 mov     pc, lr
194