Linux-2.6.12-rc2
[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:              ldrb    r3, [r0, r2, lsr #3]
29                 eors    r3, r3, #0xff           @ invert bits
30                 bne     .found                  @ any now set - found zero bit
31                 add     r2, r2, #8              @ next bit pointer
32 2:              cmp     r2, r1                  @ any more?
33                 blo     1b
34 3:              mov     r0, r1                  @ no free bits
35                 RETINSTR(mov,pc,lr)
36
37 /*
38  * Purpose  : Find next 'zero' bit
39  * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
40  */
41 ENTRY(_find_next_zero_bit_le)
42                 teq     r1, #0
43                 beq     3b
44                 ands    ip, r2, #7
45                 beq     1b                      @ If new byte, goto old routine
46                 ldrb    r3, [r0, r2, lsr #3]
47                 eor     r3, r3, #0xff           @ now looking for a 1 bit
48                 movs    r3, r3, lsr ip          @ shift off unused bits
49                 bne     .found
50                 orr     r2, r2, #7              @ if zero, then no bits here
51                 add     r2, r2, #1              @ align bit pointer
52                 b       2b                      @ loop for next bit
53
54 /*
55  * Purpose  : Find a 'one' bit
56  * Prototype: int find_first_bit(const unsigned long *addr, unsigned int maxbit);
57  */
58 ENTRY(_find_first_bit_le)
59                 teq     r1, #0  
60                 beq     3f
61                 mov     r2, #0
62 1:              ldrb    r3, [r0, r2, lsr #3]
63                 movs    r3, r3
64                 bne     .found                  @ any now set - found zero bit
65                 add     r2, r2, #8              @ next bit pointer
66 2:              cmp     r2, r1                  @ any more?
67                 blo     1b
68 3:              mov     r0, r1                  @ no free bits
69                 RETINSTR(mov,pc,lr)
70
71 /*
72  * Purpose  : Find next 'one' bit
73  * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
74  */
75 ENTRY(_find_next_bit_le)
76                 teq     r1, #0
77                 beq     3b
78                 ands    ip, r2, #7
79                 beq     1b                      @ If new byte, goto old routine
80                 ldrb    r3, [r0, r2, lsr #3]
81                 movs    r3, r3, lsr ip          @ shift off unused bits
82                 bne     .found
83                 orr     r2, r2, #7              @ if zero, then no bits here
84                 add     r2, r2, #1              @ align bit pointer
85                 b       2b                      @ loop for next bit
86
87 #ifdef __ARMEB__
88
89 ENTRY(_find_first_zero_bit_be)
90                 teq     r1, #0
91                 beq     3f
92                 mov     r2, #0
93 1:              eor     r3, r2, #0x18           @ big endian byte ordering
94                 ldrb    r3, [r0, r3, lsr #3]
95                 eors    r3, r3, #0xff           @ invert bits
96                 bne     .found                  @ any now set - found zero bit
97                 add     r2, r2, #8              @ next bit pointer
98 2:              cmp     r2, r1                  @ any more?
99                 blo     1b
100 3:              mov     r0, r1                  @ no free bits
101                 RETINSTR(mov,pc,lr)
102
103 ENTRY(_find_next_zero_bit_be)
104                 teq     r1, #0
105                 beq     3b
106                 ands    ip, r2, #7
107                 beq     1b                      @ If new byte, goto old routine
108                 eor     r3, r2, #0x18           @ big endian byte ordering
109                 ldrb    r3, [r0, r3, lsr #3]
110                 eor     r3, r3, #0xff           @ now looking for a 1 bit
111                 movs    r3, r3, lsr ip          @ shift off unused bits
112                 bne     .found
113                 orr     r2, r2, #7              @ if zero, then no bits here
114                 add     r2, r2, #1              @ align bit pointer
115                 b       2b                      @ loop for next bit
116
117 ENTRY(_find_first_bit_be)
118                 teq     r1, #0
119                 beq     3f
120                 mov     r2, #0
121 1:              eor     r3, r2, #0x18           @ big endian byte ordering
122                 ldrb    r3, [r0, r3, lsr #3]
123                 movs    r3, r3
124                 bne     .found                  @ any now set - found zero bit
125                 add     r2, r2, #8              @ next bit pointer
126 2:              cmp     r2, r1                  @ any more?
127                 blo     1b
128 3:              mov     r0, r1                  @ no free bits
129                 RETINSTR(mov,pc,lr)
130
131 ENTRY(_find_next_bit_be)
132                 teq     r1, #0
133                 beq     3b
134                 ands    ip, r2, #7
135                 beq     1b                      @ If new byte, goto old routine
136                 eor     r3, r2, #0x18           @ big endian byte ordering
137                 ldrb    r3, [r0, r3, lsr #3]
138                 movs    r3, r3, lsr ip          @ shift off unused bits
139                 bne     .found
140                 orr     r2, r2, #7              @ if zero, then no bits here
141                 add     r2, r2, #1              @ align bit pointer
142                 b       2b                      @ loop for next bit
143
144 #endif
145
146 /*
147  * One or more bits in the LSB of r3 are assumed to be set.
148  */
149 .found:
150 #if __LINUX_ARM_ARCH__ >= 5
151                 rsb     r1, r3, #0
152                 and     r3, r3, r1
153                 clz     r3, r3
154                 rsb     r3, r3, #31
155                 add     r0, r2, r3
156 #else
157                 tst     r3, #0x0f
158                 addeq   r2, r2, #4
159                 movne   r3, r3, lsl #4
160                 tst     r3, #0x30
161                 addeq   r2, r2, #2
162                 movne   r3, r3, lsl #2
163                 tst     r3, #0x40
164                 addeq   r2, r2, #1
165                 mov     r0, r2
166 #endif
167                 RETINSTR(mov,pc,lr)
168